JX通信社エンジニアブログJX通信社エンジニアブログ2020-06-22ReactのコードをHooksにリファクタリングしていく話フロントエンジニアの渡辺(@pentla)です。緊急情報サービスの「FASTALERT」は、Reactをフロントエンドのスタックとして採用しており、3年ほどコードベースは大きく変えずに運用しています。TypeScriptへのスタックの変更など、継続的にリファクタリングを進めています。tech.jxpress.net今回は、Classベースのコンポーネントを、Hooksを使って関数ベースのコンポーネントに書き直す話です。今回の対象読者は、Reactを書いたことがある方Reactのパフォーマンスについて気になっている方Hooksは知っているけれど、プロダクション環境に入れるか迷っている方を対象にしています。Hooksとはv16.8から追加された機能です。今までは、Stateやライフサイクルメソッド(表示時に一度だけ呼び出したいときなど)の機能はClassを使って書く必要があったのですが、このHooksを使えば関数ベースのコンポーネントでもStateを扱えたり、「表示後に一度だけ呼び出したい」などの要件を満たすことができるようになりました。他にもHooksを使うことで利点があり、このあたりに書かれているので、実際に使おうと思っている方は一読の価値ありです。ja.reactjs.orgそれぞれのHooksの特徴hooksはライフサイクルの考え方が少し特殊で、最初はやや違和感があるかもしれませんが、少しずつ慣れていくと、思い通りにコンポーネントの状態を管理することができます。簡単なhooksの紹介をします。useStatestateの書き方を変えるだけなので、最もわかりやすいです。useState(false)公式ドキュメント「useState」useEffectcomponentDidUpdateなど、特定のタイミングでのみ起動させたいときは、useEffectを使います。気を付けたいのは、第二引数です。useEffectの中で使用している変数、関数についてはすべてuseEffectの第二引数の配列に入れます。この引数に値を入れることで、「この中の値に変化があった場合のみ、useEffectの中の処理を走らせる」ことができます。副作用のスキップによるパフォーマンス改善」に詳しい処理の内容があります。リファクタリングのモチベーションReactのライフサイクルメソッドに、今後いくつかの修正が入ります。具体的には、ComponentWillReceiveProps、ComponentWillMount、ComponentWillUpdateの3つの関数がdeprecatedになります。この機能は、Reactのv17.0以降削除されることが決まっていて、その際はUNSAFE_というプレフィックスをつけることが求められます。新しいライフサイクルメソッドを使って書き直すことも可能ですが、せっかくの機会なので、少しずつ関数ベースのコンポーネントに書き直しています。Hooksに書き直したときの利点コード量が減った明らかに減ります。このようにstateを少し使った簡単なコンポーネントであれば、行数もかなりの数減らせることができます。MemberListパフォーマンスの考え方がわかりやすくなったMemo化を使うと、描画の際のパフォーマンスの調整が簡単になります。useMemoなどメモ化を使用することで変数ごとに計算回数の調整がしやすいです。今までは、shouldComponentUpdate関数を使って、「このコンポーネントをいつ描画するか」を管理する必要がありました。下は、webページにタイトルを表示するReact.Compoentの例です。}Titleコンポーネントには、すっごく重い処理が書かれています。Titleコンポーネントは、Parentコンポーネントの内部にあります。仮に、Parentコンポーネントが再度描画された場合、このTitleコンポーネントは変更がないにもかかわらず、再度描画処理が走ってしまいます。この場合、titleは変更がないにもかかわらず大きい処理が走ってしまい、パフォーマンスに影響が出るケースがあります。そのようなケースに対応するために、shouldComponentUpdate関数で、props.titleに変更がなければ描画しないようにするpureComponentを使うなどの対策を取る必要がありました。Memo化を使うと、このようになります。<div>{props.title}</div>}useMemoを使うことで、props.titleに変更がない限り、再度重い処理が走ることはありません。useMemoの使い方については、下にも説明を記載しています。書き直していく上でのtipsここからは、FASTALERTを実際にリファクタリングした時の話です。Componentに書き直していくことをお勧めします。小さいコンポーネントであればその分修正も少なく、挙動の変更も確認しやすいです。無理に書き直さない特にテストがないコンポーネントの場合や、ライフサイクルメソッドに複雑な処理を書いている場合、大きな変更を入れるとどうしても変更が読めない箇所というのも出てしまいます。目的は将来のアップデートに追従するためで、必ず全てのコンポーネントをhooksを使って書き直す必要はないので、代わりのメソッドで置き換えるか、一旦後回しにする選択肢をとっています。書き直している途中に明らかにパフォーマンスが悪い箇所があるAPIの呼び出し箇所のコードがわかりづらく、簡潔でない箇所に気づけたりして、問題になる前にコードの見直しができたのも良かったです。コードの行数も目に見えて減るので、効果がわかりやすいです。フロントエンドまわりを頑張っています。パターン...取締役の小笠原(@yamitzky)です。Corp.引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。