BluePeriod Docs
開発トラブルシューティング

React State Management Troubleshooting

Reactの状態管理に関する一般的な問題と解決策

React State Management Troubleshooting

このドキュメントは、Reactの状態管理に関する一般的な問題と解決策を記録します。

問題1: propsの変更が内部stateに反映されない

症状

  • 親コンポーネントからpropsとして渡されるデータが変更されても、子コンポーネントのUIが更新されない
  • サーバーサイドやAPIレスポンスでは正しいデータが返されているが、画面に反映されない
  • コンソールログでは正しい値が表示されるが、レンダリングされる内容は古いまま

根本原因

ReactのuseStateフックは、コンポーネントの初回レンダリング時のみ初期値を使用します。その後、propsが変更されても、内部stateは自動的には更新されません。

// ❌ 問題のあるコード
export const MyComponent = ({ initialData }) => {
    const [data, setData] = useState(initialData);
    // initialDataが変更されても、dataは更新されない
    
    return <div>{data.map(item => ...)}</div>;
};

解決策

方法1: useEffectで同期する(推奨)

propsの変更を検知して、内部stateを更新します。

// ✅ 解決策
export const MyComponent = ({ initialData }) => {
    const [data, setData] = useState(initialData);
    
    // propsが変更されたら内部stateを更新
    useEffect(() => {
        setData(initialData);
    }, [initialData]);
    
    return <div>{data.map(item => ...)}</div>;
};

方法2: propsを直接使用する

内部で状態を変更する必要がない場合は、propsを直接使用します。

// ✅ より良い解決策(状態変更が不要な場合)
export const MyComponent = ({ data }) => {
    // 内部stateを使わず、propsを直接使用
    return <div>{data.map(item => ...)}</div>;
};

方法3: keyプロパティでコンポーネントを再マウント

データが完全に変わる場合は、keyを使ってコンポーネントを再マウントします。

// ✅ 代替案(データが完全に変わる場合)
<MyComponent key={dataId} initialData={data} />

実際の事例: Libraryページの検索フィルタリング

状況:

  • LibraryPageClientコンポーネントが、親からinitialItemsを受け取る
  • 検索やタグフィルタリングで親コンポーネントが再レンダリングされ、新しいinitialItemsが渡される
  • しかし、UIには反映されない

原因:

export const LibraryPageClient = ({ initialItems }) => {
    const [items, setItems] = useState(initialItems);
    // ↑ 初回のみinitialItemsを使用。その後の変更は無視される

解決:

export const LibraryPageClient = ({ initialItems }) => {
    const [items, setItems] = useState(initialItems);
    
    // initialItemsが変更されたら内部stateを更新
    useEffect(() => {
        setItems(initialItems);
    }, [initialItems]);

関連する問題

Next.jsのサーバーコンポーネントとキャッシュ

Next.jsのサーバーコンポーネントはデフォルトでキャッシュされるため、検索パラメータが変わってもページが再レンダリングされない場合があります。

解決策:

// ページコンポーネントに追加
export const dynamic = 'force-dynamic';

ベストプラクティス

  1. propsを直接使用できないか検討する

    • 内部で状態を変更する必要がない場合は、propsを直接使用する方がシンプル
  2. useEffectの依存配列を正しく設定する

    • 依存配列に必要な値をすべて含める
    • ESLintのreact-hooks/exhaustive-depsルールに従う
  3. パフォーマンスを考慮する

    • propsが頻繁に変更される場合、useMemouseCallbackを検討
    • 不要な再レンダリングを避けるため、依存配列を最小限にする
  4. デバッグ方法

    • useEffect内でコンソールログを出力して、いつ更新されるか確認
    • React DevToolsで props と state の変化を追跡

参考リンク


最終更新: 2025-11-27
関連タスク: feat-explore-phase7d (Explore/Library/MyWorksページのUI統一)

On this page