作りって学ぶReact ~アコーディオン編~

アバター画像 sakurai

8

こんにちは。櫻井です。 手を動かしながら学ぶのっていいですよね。 今回はReactで実用的なアコーディオンを作成しながら学んだことを記事にしていこうと思います。

ということで出来上がったものが上記になります。 順を追って説明していきます。

まとめて情報を子コンポーネントに渡すコンテクスト

どうでもいいですがずっとコンテ”キ”ストだと思っていたんですがコンテ”ク”ストだったみたいです。

今回はアコーディオンなのでボタンと開閉するコンテンツに開閉の状態を伝える情報を渡すんですが、一つ一つにpropsを渡す方法もありますがコンテクストを使ってまとめて渡す方がシンプルになるのでコンテキストを使っています。 まず

const AccordionContext = createContext();

でコンテキストを定義してAccordionコンポーネントをAccordionContext.Providerで囲みvalueで情報を中に入る子コンポーネントに渡します。 受け取る側の子コンポーネントはuseContext(AccordionContext)でデータを受け取ります。

開閉の状態を管理するuseState

これ知らなかったんですが

const [open, setOpen] = useState(false);
function toggleOpen() {
  return setOpen(!open);
}

この書き方よくないみたいですね。

setOpenに関数を渡してあげると良いみたいです。 つまり

const [open, setOpen] = useState(false);
function toggleOpen() {
  return setOpen((prev) => !prev);
}

とするのがいいみたいです。

開閉の状態に合わせて変化させるuseRefとuseEffect

useRefを使ってアコーディオンの非表示にしている箇所の高さを取得しています。

useRefはまず

const contentRef = useRef(null);

で定義してDOMにref属性を使ってref={contentRef}でDOMを操作できるようになります。

あとは、useEffectを使って開閉状態が変更されたときにcontentRefの高さを変更することでアコーディオンを閉じたり開いたりしています。

勉強になったこと

説明は異常になるので最後に勉強になったことをまとめていきます。

コンポーネントを定義するときはネストにしない方がいいらしい

予期しないStateの引き継ぎが発生したりするみたいであんまりコンポーネントの中でさらにコンポーネント定義とかしない方がいいみたいです。

初めは

Accordion.Trigger = () ⇒ {
  //
}

みたいにしていました。

そしてこれを知って直す過程で知ったのが

export defaultってあんまり良くないらしい

exportって複数できたと思うんだけどなんでエラー出てるのかな?と思って調べてみたらexport defaultは一つのみしかできないことがわかりました。

さらにexport defaultの場合名前を変更できてしまうので良くないんだとか。なるほどなー。

そして次が最後です。正直一番勉強になったかもしれません。

関数は純関数であるべき

Reactドキュメントの「レンダーコードは純粋でなければなりません」というのをみて純粋ってどういうこと??ってなって調べてみたらqiitaにわかりやすい記事がありました。

要するに毎回同じ引数渡してるのに帰ってくる値が変わったり、関数が関数の外の変数とかに影響与えちゃダメでしょって話しだと解釈したんですがそりゃそうだとなると同時にそういう書き方してないか注意しないといけないなとなりました。

それにしてもReactの日本語ドキュメントいつの間にこんなに充実していたんですかね? 少し前までほとんど英語何書いてあるか全くわからず絶望していたんですが、これだけ充実してくれるととても助かります。

参考リンク

createContext

コンテクストで深くデータを受け渡す

useRef

useEffect

エフェクトを使って同期を行う

コンポーネントを純粋に保つ

export default とexport constの違い

【React】そろそろ技術ブログで setCount(count + 1) と書くのはやめませんか

アバター画像

ぽちっとおうえん!

シェア

  • Facebook
  • LINE
  • X
KNAPのエンジニアが感性を鍛えるために始めたこと チーム「犬」。活動内容ご報告します。