7.1 コンポーネントの生存期間

関数コンポーネントにクラスのようなインスタンスライフサイクルがあると考えるより、次を区別する。

  • コンポーネントがツリーへ追加される
  • props・state・Contextの変化で再レンダリングされる
  • ツリーから削除される
  • Effectが同期を開始・再同期・停止する

7.2 再レンダリングの主な原因

  • 自身のstate更新
  • 親の再レンダリング
  • 利用しているContextの更新
  • 外部ストアの通知

propsが同じでも、親が再レンダリングすると通常は子も評価される。DOMが必ず更新されるわけではない。

7.3 Reconciliation

Reactは前回と今回の要素ツリーを比較し、必要な変更を決定する。

基本規則:

  • 異なる要素型は別ツリーとして扱う
  • 同じ要素型は属性を更新する
  • 同階層の一覧はkeyで対応付ける
  • 同じ位置・同じ型はstateを保持する

7.4 Strict Modeで見つかる問題

  • レンダリング中の副作用
  • Effectクリーンアップ不足
  • refコールバックの後処理不足
  • 非推奨API

本番の実行回数を模倣する機能ではなく、再実行に弱いコードを検出する仕組みである。

7.5 エラー境界

レンダリング中のエラーを受け止め、代替UIを表示する。

現時点では一般的なエラー境界はクラスコンポーネントで実装するか、ライブラリ・フレームワークの仕組みを使う。

class ErrorBoundary extends React.Component<
  React.PropsWithChildren,
  { hasError: boolean }
> {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    reportError(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <p role="alert">表示に失敗しました。</p>;
    }

    return this.props.children;
  }
}

イベントハンドラー内のエラーや任意の非同期エラーは、自動的には捕捉されない。