推移的に到達可能なすべての状態を含む反応コンポーネントをリセットするにはどうすればよいですか?


93

時々、リセットしたい、概念的にステートフルな反応コンポーネントがあります。理想的な動作は、古いコンポーネントを削除して、新しい初期のコンポーネントを読み取ることと同じです。

ReactはsetState、コンポーネント自身の明示的な状態を設定できるメソッドを提供しますが、ブラウザーのフォーカスやフォームの状態などの暗黙の状態を除外し、その子の状態も除外します。そのすべての間接的な状態をキャッチするのは難しい作業です。私は、驚くべき状態のすべての新しいビットでモグラを叩くよりも、厳密かつ完全にそれを解決することを好みます。

これを行うためのAPIまたはパターンはありますか?

編集: 私は実証簡単な例作られたthis.replaceState(this.getInitialState())アプローチをし、それを対照的なthis.setState(this.getInitialState())アプローチ:jsfiddle - replaceStateより堅牢です。

回答:


206

あなたが言及する暗黙のブラウザ状態と子の状態が確実にリセットされるようにするには、によって返されるルートレベルのコンポーネントにkey属性を追加できrenderます。変更されると、そのコンポーネントは破棄され、最初から作成されます。

render: function() {
    // ...
    return <div key={uniqueId}>
        {children}
    </div>;
}

個々のコンポーネントのローカル状態をリセットするショートカットはありません。


1
「コンポーネントは破棄されて最初から作成される」という好奇心から、仮想DOMは破棄されて最初から作成されますが、DOMの更新は差分アルゴリズムに基づいて行われますか?
nimgrg 2014

1
@nimgrgいいえ、実際のDOM要素も再作成されます。(仮想DOMはすべてのレンダリングで既に再作成されているため、実際のDOMを保持したいkey場合は、この場合はを設定しないでください。)
Sophie Alpert

3
@EamonNerbonne React 0.8では、キーは配列内の兄弟要素を区別するためにのみ使用され、ルートでは無視されました。github.com/facebook/react/issues/590を参照してください。
ソフィーアルパート2014

注意replaceState()してgetInitialState()両方の新しいES6クラススタイルのreactjsに廃止されました。this.setState(this._getInitialState())代わりに使用してください。また、独自の状態初期化関数に名前を付けることはできませんgetInitialState()-反応は警告をスローします-他の関数を呼び出してstate = this._getInitialState()、クラスのトップレベルで明示的に行います。
thom_nic 2016年

2
外部からキープロップを渡す必要なく、コンポーネントの内部からこれを行う方法はありますか?
trusktr

14

代わりに実際に避けreplaceStateて使用する必要がありますsetState

ドキュメントは、replaceState「Reactの将来のバージョンでは完全に削除される可能性がある」と述べています。replaceStateReactの哲学にあまり慣れていないので、間違いなく削除されると思います。これは、Reactコンポーネントにスイスナイフのような感覚を与えやすくします。これは、Reactコンポーネントが自然に成長して小さくなり、より目的に合わせて成長するのを妨げます。

Reactでは、一般化または特殊化について誤解する必要がある場合は、特殊化を目指してください。当然のことながら、コンポーネントの状態ツリーには一定の節約が必要です(ただし、ブランド全体の新製品を足場にする場合は、このルールを上品に破ることは問題ありません)。

とにかく、これはあなたがそれを行う方法です。上記のベンの(受け入れられた)回答に似ていますが、次のようになります。

this.setState(this.getInitialState());

また、(Benも言ったように)「ブラウザの状態」をリセットするには、そのDOMノードを削除する必要があります。vdomのパワーを活用し、keyそのコンポーネントに新しいプロップを使用します。新しいレンダリングは、そのコンポーネントの卸売を置き換えます。

リファレンス:https : //facebook.github.io/react/docs/component-api.html#replacestate


2
現在の状態に初期状態にないプロパティが含まれている場合、これは機能しません。それが良い状態だとは思っていませんが、どうにか防止できない限り、意外な破損を避けたいと思います。場合によってはクラッシュするリセットで大丈夫ですが、微妙に状態を壊すリセットではありません。
Eamon Nerbonne、2016年

わかりません。これは同等ではないと言っていthis.replaceStateますか?そうです。
wle8300

1
@ williamle8300への呼び出し間のコンポーネントのライフサイクルのどこかにgetInitialState()(たとえば、onClickハンドラーで)状態を追加するために新しいプロパティが追加された場合、これらは同等ではありません。この場合、その新しいプロパティは2番目以降も存在しgetInitialState()ます。
Graham

@Grahamでまだ宣言されていないコンポーネントに新しい状態を導入することは悪い習慣だと思いますgetInitialState。関数の上部にあるJS関数ですべての変数を宣言するのと同じです。補足:ベンアルパートのソリューションは私のソリューションとほぼ同じです...そして彼は公式のReactメンテナーです!
wle8300

1
関数getInitialState()とその答えは非推奨になっていると思います。アップデートはいいです。
マーティンR.

9

key再初期化する必要のある要素に属性を追加すると、propsまたはstate要素への関連付けが変更されるたびに属性が再ロードされます。

key = {new Date()。getTime()}

次に例を示します。

render() {
  const items = (this.props.resources) || [];
  const totalNumberOfItems = (this.props.resources.noOfItems) || 0;

  return (
    <div className="items-container">
      <PaginationContainer
        key={new Date().getTime()}
        totalNumberOfItems={totalNumberOfItems}
        items={items}
        onPageChange={this.onPageChange}
      />
    </div>
  );
}

1
または、単純な整数カウンタ変数をキーとして追加することもできます
ミニマリスト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.