Fast Refresh
Fast Refreshは、React Nativeの機能で、Reactコンポーネントの変更に対してほぼ即座にフィードバックを得ることができます。Fast Refreshはデフォルトで有効になっており、React Native開発者メニューで「Fast Refreshを有効にする」を切り替えることができます。Fast Refreshが有効な場合、ほとんどの編集は1〜2秒以内に反映されます。
仕組み
- Reactコンポーネントのみをエクスポートするモジュールを編集した場合、Fast Refreshはそのモジュールのコードのみを更新し、コンポーネントを再レンダリングします。スタイル、レンダリングロジック、イベントハンドラー、エフェクトなど、そのファイル内のあらゆるものを編集できます。
- Reactコンポーネントではないエクスポートを含むモジュールを編集した場合、Fast Refreshはそのモジュールと、それをインポートしている他のモジュールの両方を再実行します。したがって、
Button.jsとModal.jsの両方がTheme.jsをインポートしている場合、Theme.jsを編集すると両方のコンポーネントが更新されます。 - 最後に、Reactツリーの外部のモジュールにインポートされているファイルを編集した場合、Fast Refreshはフルリロードにフォールバックします。Reactコンポーネントをレンダリングするファイルがありながら、非Reactコンポーネントにインポートされる値をエクスポートしている場合があります。例えば、コンポーネントが定数もエクスポートしており、非Reactユーティリティモジュールがそれをインポートしているような場合です。その場合、定数を別のファイルに移行し、両方のファイルでインポートすることを検討してください。これにより、Fast Refreshが再び機能するようになります。他のケースも通常は同様の方法で解決できます。
エラー回復力
Fast Refreshセッション中に構文エラーが発生した場合、それを修正してファイルを再度保存することができます。レッドボックスは消えます。構文エラーのあるモジュールは実行が阻止されるため、アプリをリロードする必要はありません。
モジュール初期化中にランタイムエラーが発生した場合(例えば、StyleSheet.createの代わりにStyle.createと入力した場合など)、エラーを修正するとFast Refreshセッションが続行されます。レッドボックスは消え、モジュールが更新されます。
コンポーネント内でランタイムエラーにつながる間違いを犯した場合でも、エラーを修正するとFast Refreshセッションは続行されます。その場合、Reactは更新されたコードを使用してアプリケーションを再マウントします。
アプリにエラーバウンダリがある場合(これは本番環境での graceful な失敗のために良いアイデアです)、レッドボックスの後に次回の編集でレンダリングを再試行します。この意味で、エラーバウンダリを持つことで、常にアプリのルート画面に強制的に戻されるのを防ぐことができます。ただし、エラーバウンダリはあまり細かくしすぎないように注意してください。これらは本番環境でReactによって使用され、常に意図的に設計されるべきです。
制限事項
Fast Refreshは、編集中のコンポーネントのローカルなReactの状態を保持しようとしますが、安全な場合に限ります。ファイルへの編集ごとにローカルな状態がリセットされる可能性のある理由をいくつか示します。
- クラスコンポーネントのローカルな状態は保持されません(関数コンポーネントとHooksのみが状態を保持します)。
- 編集中のモジュールが、Reactコンポーネントに加えて他のエクスポートを持っている場合があります。
- 場合によっては、モジュールが
createNavigationContainer(MyScreen)のような高階コンポーネントの呼び出し結果をエクスポートすることがあります。返されたコンポーネントがクラスの場合、状態はリセットされます。
長期的には、コードベースのより多くが関数コンポーネントとHooksに移行するにつれて、より多くのケースで状態が保持されることが期待できます。
ヒント
- Fast Refreshは、関数コンポーネント(およびHooks)のReactローカル状態をデフォルトで保持します。
- 場合によっては、状態を強制的にリセットし、コンポーネントを再マウントしたいことがあります。例えば、マウント時にのみ発生するアニメーションを微調整している場合に便利です。これを行うには、編集中のファイル内の任意の場所に
// @refresh resetを追加できます。このディレクティブはファイルローカルであり、Fast Refreshにそのファイルで定義されたコンポーネントを編集するたびに再マウントするように指示します。
Fast RefreshとHooks
可能な場合、Fast Refreshは編集間でコンポーネントの状態を保持しようとします。特に、useStateとuseRefは、引数やHook呼び出しの順序を変更しない限り、以前の値を保持します。
useEffect、useMemo、useCallbackなどの依存関係を持つHooksは、Fast Refresh中に常に更新されます。Fast Refreshが行われている間、それらの依存関係のリストは無視されます。
例えば、useMemo(() => x * 2, [x])をuseMemo(() => x * 10, [x])に編集した場合、x(依存関係)が変更されていなくても再実行されます。Reactがそうしないと、編集が画面に反映されません!
時として、これは予期せぬ結果につながることがあります。例えば、空の依存関係配列を持つuseEffectでさえ、Fast Refresh中に一度再実行されます。しかし、useEffectのたまの再実行に耐性のあるコードを書くことは、Fast Refreshがない場合でも良い習慣です。これにより、後で新しい依存関係を導入するのが容易になります。