🚀

【Next.js和訳】Basic Features/Fast Refresh

3 min read

この記事について

株式会社 UnReact はプロジェクトの一環としてNext.js ドキュメントの和訳を行っています。

この記事は、Basic Features/Fast Refreshの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Fast Refresh

Fast RefreshはNext.jsの機能で、Reactコンポーネントに加えられた編集を瞬時にフィードバックすることができます。Fast Refreshは、9.4以降のすべてのNext.jsアプリケーションでデフォルトで有効になっています。Next.jsのFast Refreshを有効にすると、コンポーネントのstateを失うことなく、ほとんどの編集内容が1秒以内に表示されます。

仕組み

  • Reactコンポーネントのみをエクスポートしているファイルを編集すると、高速リフレッシュはそのファイルのコードのみを更新し、コンポーネントを再レンダリングします。スタイル、レンダリング ロジック、イベント ハンドラ、エフェクトなど、そのファイル内のあらゆるものを編集できます。
  • Reactコンポーネントではないエクスポートを含むファイルを編集すると、Fast Refreshはそのファイルと、それをインポートしている他のファイルの両方を再実行します。たとえば、Button.jsModal.jsの両方がtheme.jsをインポートしている場合、theme.jsを編集すると両方のコンポーネントが更新されます。
  • 最後に、Reactツリーの外にあるファイルからインポートされているファイルを編集すると、Fast Refreshはフルリロードに戻ります。Reactコンポーネントをレンダリングするが、React以外のコンポーネントによってインポートされる値もエクスポートするファイルがあるかもしれません。例えば、コンポーネントが定数をエクスポートし、React以外のユーティリティファイルがそれをインポートしているような場合です。そのような場合は、定数を別のファイルに移行し、両方のファイルにインポートすることを検討してください。これにより、高速リフレッシュが再び機能するようになります。その他のケースでも、通常は同様の方法で解決できます。

エラー修復力

シンタックスエラー

開発中にシンタックスエラーが発生した場合、エラーを修正して再度ファイルを保存することができます。エラーは自動的に消えますので、アプリを再読み込みする必要はありません。また、コンポーネントのstateが失われることもありません

ランタイムエラー

コンポーネント内でランタイムエラーにつながるミスをした場合、コンテクストオーバーレイが表示されます。エラーを修正すると、アプリをリロードすることなく、オーバーレイが自動的に解除されます。

レンダリング中にエラーが発生しなかった場合は、コンポーネントのstateが保持されます。レンダリング中にエラーが発生した場合、Reactは更新されたコードを使用してアプリケーションを再マウントします。

アプリにエラーバウンダリがある場合(本番での潔い失敗のためには良いアイデアです)、レンダリングエラーの後の次の編集でレンダリングを再試行します。つまり、エラーバウンダリを持つことで、常にルートアプリのstateにリセットされることを防ぐことができます。ただし、エラーバウンダリはあまり細かくすべきではないことに留意してください。これらはReactが本番で使用しているものであり、常に意図的に設計すべきものです。

制限事項

Fast Refreshは、編集しているコンポーネントのローカルなReactのstateを保持しようとしますが、それが安全な場合に限られます。ファイルを編集するたびにローカルのstateがリセットされることがあるのは、以下の理由によります。

  • クラスコンポーネントでは、ローカルのstateは保存されません(stateが保存されるのは、関数コンポーネントとHooksのみです)。
  • 編集中のファイルは、Reactコンポーネントに加えて他のエクスポートがあるかもしれません。
  • 時々、ファイルは、HOC(WrappedComponent)のような高次のコンポーネントを呼び出した結果をエクスポートするでしょう。返されたコンポーネントがクラスの場合、ステートはリセットされます。
  • export default () => <div />;のような匿名の矢印関数は、Fast Refreshがローカルコンポーネントのstateを保持しない原因となります。大規模なコードベースでは、name-default-component codemodを使用することができます。

コードベースの多くが関数コンポーネントやHooksに移行すると、より多くのケースでstateが保存されるようになります。

ヒント

  • Fast Refreshは、デフォルトで関数コンポーネント(およびHooks)のReactローカルのstateを保持します。
  • 時には、強制的にstateをリセットして、コンポーネントを再マウントしたいことがあります。例えば、マウント時にのみ発生するアニメーションを調整する場合などに便利です。これを行うには、編集中のファイルのどこかに// @refresh resetを追加します。このディレクティブは、ファイルにローカルなもので、編集のたびに、そのファイルで定義されたコンポーネントを再マウントするように、ファーストリフレッシュに指示します。
  • 開発中に編集するコンポーネントにconsole.logまたはdebugger;を入れることができます。

Fast RefreshとHooks

可能な限り、高速リフレッシュでは、編集の間にコンポーネントのstateを維持しようとします。特に、useStateuseRefは、その引数やHook callsの順序を変更しない限り、以前の値を維持します。

useEffectuseMemouseCallbackなどの依存関係のあるHooksは、高速更新時に常に更新されます。依存関係のリストは、高速更新が行われている間は無視されます。

例えば、useMemo(() => x * 2, [x])useMemo(() => x * 10, [x])に編集すると、x(依存関係)が変わっていないのに再実行されます。もしReactがそうしてくれなかったら、編集した内容は画面に反映されないでしょう

時には、これが予想外の結果をもたらすこともあります。例えば、依存関係の配列が空のuseEffectであっても、Fast Refresh中に一度は再実行されてしまいます。

しかし、時折発生するuseEffectの再実行に強いコードを書くことは、Fast Refreshがなくても良い習慣です。後で新しい依存関係を導入するのが簡単になりますし、React Strict Modeによって強制されますので、有効にすることを強くお勧めします。

Discussion

ログインするとコメントできます