🧐

MUIのAccordionで3階層チェックリストを作ったときの学び

2022/08/11に公開

まえがき

仕事ではスケジュールがカツカツな業務アプリの実装を、
プライベートでは引っ越しをしており、なかなか学習に時間を使えていないのですが、
業務アプリでフロントを実装しているときに、
フロントエンドエンジニアの方に色々教わり、学びがあったのでこれをネタにしたいと思います

どういうことをやろうとしていたのか

このように3階層のチェックリストのモーダルを作ろうとしていました。
コンテンツの数は
1層:約10種類
2層:約10種類
3層:約20種類
合計2,000近いコンテンツになりました。

これを実装するにあたり、躓いた事・解決方法をまとめておきます

学んだこと

Accordionのコンテンツ数が多くてレンダリングが遅くなる

これはMUIのドキュメントにも書かれているんですが、
Accordionに渡されたコンテンツはサーバー側のレンダリングとSEOを考慮して、デフォルトでは全てマウントしてレンダリングされてしまいます。
そのため、項目数が多いコンテンツはそのレンダリングに数〜数十秒かかります。
実際、自分が実装していた3階層Accordionははじめに書いたように2,000近いコンテンツ数だったため、表示されるのにそれぐらいかかりました。

解決方法

解決方法もちゃんとドキュメントに書かれていました。
Accordionを展開するタイミングで、その配下の階層がレンダリングされるように次の記述を行うことで解消することができます。

<Accordion TransitionProps={{ unmountOnExit: true }} />

チェックボックスのonClickとAccordionのexpandedが同時に動作する

MUIとreact-hook-formを使って次のような実装をしていたのですが、

<Accordion TransitionProps={{ unmountOnExit: true }}>
  <AccordionSummary>
    <FormControlLabel
      control={
        <Controller
	  control={control}
	  render={({ field }) => {
	    return (
	      <Checkbox
	        onChange={() => {
		}}
	      />
	    );
	  }}
        />
      }
    />
  </AccordionSummary>
  <AccordionDetails>
  </AccordionDetails>
</Accordion>

このとき、チェックボックスのonClickの判定領域とAccordionexpandedの判定領域が重なっているため、両方発火してチェックが付くのと同時にAccordionが閉じたり開いたりという事象が発生しました。

解決方法

この問題の解決方法はonClickeventがもつstopPropagation()で、
親コンポーネント(Accordion)にイベントが伝搬しないようにすることで解決することを教わりました。

<Checkbox
  onClick={(e) => e.stopPropagation()}
/>
// または
<FormControlLabel
  onClick={(e) => e.stopPropagation()}
/>

おまけ

今作っている業務アプリを通して、
フロントエンドエンジニアの方にReactのFormにはControlledとUncontrolledがあることを教わりました。

https://zenn.dev/tns_00/articles/react-controlled-and-uncontrolled
https://qiita.com/kotarella1110/items/da32add730e2b5451704

react-hook-formはUncontrolledを採用しているそうです。

そういう概念があることは分かったんですが、
自分が知らないところでControlled, Uncontrolledが切り替わってしまい、
エラーが出て悩まされる日々です。

今回の事とこのFormの仕様などを新たに知って、フロントは奥が深いなと痛感しました。

Discussion