🗂

React Docs BETAを読む 【状態の保持とリセット】

2022/07/09に公開

React Docs BETAを読む 【状態の管理】
React Docs BETAを読む 【Stateで入力に反応する】
React Docs BETAを読む 【状態構造の選択】
React Docs BETAを読む 【コンポーネント間で状態を共有する】
に引き続き状態管理の章を読み進めていきます。
本日は状態の保存とリセットという章です。

Preserving and Resetting State

状態の保持とリレンダー間でリセットするタイミングはコントロールできます。

The UI tree

ReactはJSXからUIツリーを作成しReact DOMがブラウザのDOM要素をUIツリーに合わせて更新します。
ツリー構造で管理しているのはインターフェース名などからわかりますね。
レンダリングに関する記述でもツリー構造について触れていた気がします。

State is tied to a position in the tree

状態はツリー内の位置に関連付けられているという節です。
実装をしていると、コンポーネントが状態を持っている(ドキュメントでは住んでいると書いてある)感覚になりますよね。
実際にはReactが状態を保持していて、UIツリー上のコンポーネントの位置によって関連付けているようです。
同じコンポーネントを2つレンダリングしてもそれぞれの状態が独立しているのがわかりやすい例だと思います。
この状態はUIツリー上の同じ位置にレンダリングする限り値は保持されます。
コンポーネントが削除された場合と、同じ位置に別コンポーネントがレンダリングされた場合はその状態は破棄されます。

Same component at the same position preserves state

同じ場所の同じコンポーネントは状態が保持される場合についての節です。
以下のように条件付きレンダーなどで同じコンポーネントを切り替えている場合があるとします。

isStyled ? <ComponentA styled={hoge} /> : <ComponentA styled={bar} />

isStyledが切り替われば表示されるコンポーネントは変更されますが、コンポーネントと位置は同じです。
この場合は状態は保持されたままになります。
先程も書いた通り、UIツリー状のコンポーネントの位置と状態が関連付けられているためです。

Different components at the same position reset state

先程とは異なり、同じ位置の別のコンポーネントは状態がリセットさせます。

isStyled ? <ComponentA styled={hoge} /> : <ComponentB styled={hoge} />

上記のような場合ComponentAComponentBは別のものなので同じ位置にレンダーされたときには状態はリセットされます。
順番としてはUIツリーからコンポーネントが削除され、状態が破棄される。
そして別コンポーネントが同じ位置にレンダリングされるといった流れですかね。
以下のように同じコンポーネントがネストされていて親が異なる場合でも同様です。

isStyled ? (
        <div>
            <ComponentA styled={hoge} /> 
        </div>
    )
    :(
        <section>
            <ComponentA styled={hoge} />
        </section>
    )

この場合もUIツリー上から親コンポーネント以下が削除されるためComponentAの状態は破棄されます。
落とし穴として、コンポーネントの宣言がネストする場合も同じようにリセットが起こることが言及されています。

Resetting state at the same position

同じ位置の状態をリセットするという節です。
これまでの性質から、同じ位置にレンダーされる同じコンポーネントは状態を維持し続けます。
場合によっては、それを切り替えるごとにリセットしたい場合などが出てくると思います。
こういう場合の方法は2つあります。

  1. 異なる位置にコンポーネントをレンダーする。
  2. 各コンポーネントにキーを設定して明示的に一意にする。

1. 異なる位置にコンポーネントをレンダーする。

例えば以下の実装します。

// 同じ位置にレンダーされる
isStyled ? <ComponentA styled={hoge} /> : <ComponentA styled={bar} />

// 異なる位置にレンダーされる
isStyled && <ComponentA styled={hoge} /> 
!isStyled && <ComponentA styled={bar} />

このパターンは同じ位置に表示するコンポーネントが少ない場合に有効です。

2. 各コンポーネントにキーを付与して明示的に一意にする。

リストなどでKeyを付与することがあると思います。
それと同様にコンポーネントにKeyを付与することでReactに明示的にこれは別々のコンポーネントだと伝えることができます。

// 同じコンポーネントと認識される。
isStyled ? <ComponentA styled={hoge} /> : <ComponentA styled={bar} />

//keyを付与することで別コンポーネントと認識される。
isStyled ? 
    <ComponentA key="hoge" styled={hoge} /> 
    : 
    <ComponentA key="bar" styled={bar} />

Resetting a form with a key

キーを利用してフォームをリセットする方法についての節です。
フォームを実装しているコンポーネントでもkeyを付与することでリセットを書けることができます。

まとめ

状態の保持とリセットについて学びました。
Reactがどのようにして状態を管理しているのかを知らなかったため、とても有意義でした。
なぜ状態が保持される場合とリセットされる場合があるのかなど、仕組みから理解することができました。
実際の実装でも使う場面は多いと思うのでしっかり覚えておきたいところです。

GitHubで編集を提案

Discussion