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