B.1 propsをstateへ無条件コピーする

function Editor({ user }: { user: User }) {
  const [name, setName] = useState(user.name);
}

userが変わっても自動同期されない。編集ドラフトとして意図的なら、保存・破棄・ユーザー切り替え時の仕様を明示する。単なる表示ならpropsを直接使う。

B.2 Effectで派生値を更新する

useEffect(() => {
  setFiltered(items.filter(filterFn));
}, [items, filterFn]);

レンダリング中に計算する。重い場合はCompilerまたは計測後のメモ化を検討する。

B.3 indexを不安定な一覧のkeyにする

入力欄の値や子stateが別行へ移動する原因になる。

B.4 stateを直接変更する

user.name = nextName;
setUser(user);

新しいオブジェクトを作る。

B.5 コンポーネント内でコンポーネントを定義する

再レンダリングごとに型が変わり、stateリセットや不要な処理につながる。

B.6 Contextへ全stateを入れる

一箇所の更新が広い再レンダリングを起こし、責務が曖昧になる。更新頻度・利用範囲で分割する。

B.7 useMemoを正しさのために使う

キャッシュが存在することを前提に設計しない。

B.8 依存配列から値を削除する

ESLintを黙らせるために依存値を除外すると、古い値を参照する。コード構造を変更する。

B.9 Effectでイベント処理を表現する

操作の発生場所が分かっているならイベントハンドラーで実行する。

B.10 Client Componentを広げすぎる

RSC環境でルート近くに'use client'を置くと、多くの依存がクライアントbundleへ入る。インタラクティブな境界を下げる。

B.11 Server Functionを信頼する

サーバーで実行されるだけで安全になるわけではない。公開APIとして検証・認可する。

B.12 ローディングを単一booleanで表す

初回、再取得、送信、追加取得を区別する。

B.13 巨大な万能コンポーネント

取得、変換、フォーム、表示、モーダル、通知を一つに入れない。変更理由とテスト境界で分割する。

B.14 早すぎる最適化

計測せずmemouseMemouseCallbackを全面適用しない。React Compiler環境では特に重複しやすい。