1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Reactクイズ】条件分岐で同じコンポーネントを出し分けるとステートがリセットされる理由

Posted at

はじめに

uhyoさんの「今日のReactクイズ」で紹介されていた問題を実際に検証してみました。
チェックボックスを切り替えるとCounterのステートがリセットされる現象について、その原因と対処法をまとめます。

問題のコード

export default function App() {
  const [checked, setChecked] = useState(false);
  return (
    <div className="App">
      <p>
        <input
          type="checkbox"
          checked={checked}
          onClick={() => setChecked((c) => !c)}
        />
      </p>
      {!checked && <Counter />}
      {checked && <Counter />}
    </div>
  );
}

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <p>
      <button type="button" onClick={() => setCount((c) => c + 1)}>
        {count}
      </button>
    </p>
  );
}

クイズの答え:リセットされる

このコードでは、チェックボックスを切り替えるたびにカウンターがリセットされます

uhyo-checkbox-reset-problem-1.gif

なぜリセットされるのか

理由は、Reactのコンポーネント識別の仕組みにあります。

{!checked && <Counter />}  // 1つ目の位置
{checked && <Counter />}   // 2つ目の位置

この2つの<Counter />は、DOMツリー上の異なる位置に配置されています。
Reactは、checkedの値が変わると:

  1. 古い位置の<Counter />をアンマウント(破棄)
  2. 新しい位置に別の<Counter />をマウント(新規作成)

という処理を行います。その結果、内部のstateもリセットされます。

対処法(本来は不要だが)

クイズの本質は「リセットされることを理解する」ことですが、もし保持したい場合の解決策を紹介します。

解決策1:keyプロパティを使用

{!checked && <Counter key="counter" />}
{checked && <Counter key="counter" />}

同じkeyを持つことで、Reactは同一コンポーネントとして認識します。

解決策2:条件分岐をなくす

export default function App() {
  const [checked, setChecked] = useState(false);
  return (
    <div className="App">
      <p>
        <input
          type="checkbox"
          checked={checked}
          onClick={() => setChecked((c) => !c)}
        />
      </p>
      <Counter />
    </div>
  );
}

そもそも条件分岐せず、常に同じ位置に配置すればリセットされません。

まとめ

  • Reactは条件分岐で異なる位置に配置されたコンポーネントを別物として扱う
  • そのため、条件が変わるとstateがリセットされる
  • 理解することが重要で、無理に保持しようとする必要はない
  • どうしても保持したい場合はkeyを使うか、条件分岐をなくす

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?