JavaScript PR

【React小ネタ】同じ位置にあるコンポーネントのStateは共有される

記事内に商品プロモーションを含む場合があります

Reactの勉強をしている中で、
「おぉそうなんだ、知らなかった」みたいな
小ネタを入手したらメモがてらまとめようと思います。
今回は、Reactで同じ位置にあるコンポーネントのStateは
共有されるということを学んだのでメモっておきます!

同じ位置にあるコンポーネントのStateは共有される

以下のサンプルコードでは、
Sampleコンポーネント内でtoggleというStateが管理されています。
このStateによって、表示されるコンポーネントが
CountコンポーネントのAまたはBに切り替わります。

Sample-Count-A
Sample-Count-B
import { useState } from "react";

const Sample = () => {
  const [toggle, setToggle] = useState(true);

  const toggleComponent = () => {
    setToggle(prev => !prev);
  }

  return (
    <>
      <button onClick={toggleComponent}>A/B切り替え</button>
      {toggle ? <Count title="A"/> : <Count title="B"/>}
    </>
  );
};


上記Countコンポーネントは、
titleとして受け取った文字列とカウント数を表示し、
+ボタンおよび-ボタンを押すことでカウントを変更できるようになっています。

const Count = ({ title }) => {
  const [count, setCount] = useState(0);

  const countUp = () => {
    setCount(prevstate => prevstate + 1);
  };

  const countDown = () => {
    setCount(count - 1);
  };

  return (
    <>
      <h3>{title}: {count}</h3>
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </>
  );
};

ここで重要なポイントは、
Sampleコンポーネント内で
二つのCountコンポーネントが同じ位置に存在していることです。

この例では、ボタンによりCountコンポーネントのA⇄Bが切り替わりますが、
countの状態はリセットされません。
これは、ReactはあくまでJSXから生成されたUI Treeにおける位置を参照しており、
A/Bの表示が切り替わったとしても、
そのコンポーネントは同じ位置に配置されるので、
同じコンポーネントと見なされるということです。

なかなか、へぇそうなんだ!と驚きでした。

ちなみに、同じ位置、階層になければState共有されないので、
以下のようにdivタグなどを挟んで位置を変えてやれば、
このStateの共有は起きません!

    <>
      <button onClick={toggleComponent}>A/B切り替え</button>
      {toggle ? <Count title="A"/> : <div><Count title="B"/></div>}
    </>

まとめ

さて、前述のように
ReactではコンポーネントのStateをその内部で保持するわけではなく、
「この位置にあるコンポーネントの状態はこれだ」というように、
コンポーネントとその状態をUI Treeにおける位置により紐づけます。

  • コンポーネントの位置が変わらなければ状態は保持される
  • コンポーネントの位置が変われば状態がリセットされる

このような仕組みをきちんと理解することで、効果的にStateを管理し、
コンポーネント間で情報を共有できるようになると思いますので、
是非、皆様もこの概念を理解して、Reactアプリケーションの開発に役立ててください!