web-dev-qa-db-ja.com

React + Flux-保存するデータはコンポーネント状態、または小道具に保存する必要がありますか?

フラックスストアがデータの状態を保持するシングルトンである場合、ストアへのアクセス時にコンポーネントがsetPropsではなくsetStateを使用するのはなぜですか?アプリケーションの状態を2つ(またはそれ以上)の場所に保存し始めたというだけではありませんか?

Flux/Reactドキュメンテーションと例は両方ともsetStateを推奨ソリューションとして示しているようですが、職場の同僚と興味深い会話をし、他の誰かがこれに遭遇したかどうか疑問に思いました

編集:このURLで私が話していることを見ることができます: https://github.com/facebook/flux/blob/master/examples/flux-chat/js/components/ThreadSection.react.js

ThreadSectionが子コンポーネントであり、ストアから直接データを取得し、それを状態として使用していることに注目してください。

React "way"に従うと、子コンポーネントではなく、ストアによって状態が管理されると予想されます。

私たちが考えた解決策は、最上位コンポーネントのすべてのストアを(小道具として)フェッチし、必要に応じてそれらを子コンポーネントに渡すことです。しかし、それはかなりquicklyく、かなり速くなります。

これは、setPropsが子コンポーネントで機能しないためです

25
Guy Nesher

2種類のコンポーネントが必要であることを理解してください。ステートフルコンポーネントとビューコンポーネント。

ステートフルコンポーネントには、初期状態、ユーザー入力状態、データストア状態の3種類の状態があります。

ステートフルコンポーネントは、組み立てる「ウィジェット」の小さなエントリポイントのようなものです。これらのウィジェットはすべて独自の独立したライフサイクルを持っているため、ダウンストリームの依存関係やデータインジェクションのための単一のアプリケーション全体のエントリポイントはもうありません。だからこそ、彼ら自身がストアにアクセスして聴く必要があるのです。

挙動プロパティに加えて、ステートフルコンポーネントは、アップストリームプロパティを介して実際のデータを受け取りません。

ステートフルコンポーネントは独自の状態を管理し、それを子に渡し、ダウンストリームプロパティを介してレンダリングします。

ステートフルコンポーネントは通常、html DOM要素自体を直接レンダリングしません。 MVCのコントローラーに似ており、MVCのビューのような他のコンポーネントを使用して、実際にDOM要素をレンダリングします。

Dumberコンポーネントはビューに似ているため、DOM要素をレンダリングするロジックのみが含まれています。プロパティのみを受け取るhandlebars.jsテンプレートと考え、ループなどでDOM要素に単純にレンダリングします。これらはステートレスレンダラーです。

これがあなたの質問に答えることを願っています。

43
Rygu

正式な文書によると、ストアは親コンポーネントの状態を更新し、子供の小道具を介してそれを渡す必要があります。

ストアからイベントを受信すると、まずストアのパブリックgetterメソッドを介して必要な新しいデータを要求します。次に、独自のsetState()またはforceUpdate()メソッドを呼び出して、そのrender()メソッドとそのすべての子孫のrender()メソッドを実行します。

多くの場合、ストアの状態全体を単一オブジェクトのビューチェーンに渡し、異なる子孫が必要なものを使用できるようにします。コントローラーのような動作を階層の最上部に保持し、子孫ビューを機能的にできるだけ純粋に保つことに加えて、ストアの状態全体を1つのオブジェクトに渡すことで、小道具の数を減らす効果もあります。管理する必要があります。

(facebook flux docs-概要)

7
yarden

ストアデータをコンポーネントの状態にする方が理にかなっています。これは、 componentWillReceiveProps を使用して親コンポーネントによって小道具が変更される可能性があるためです。したがって、次の場合はいつでもstateを更新するのが理にかなっています。

  • ストアの変更イベントが発生し、
  • 小道具が変更されるたびに(コンポーネント自体のみに関連する派生データを状態に置く)

以下は、 reflux store をリッスンし、また小道具の変更を更新するサンプルコンポーネントです。私はめったにthis.propsは、render関数で、代わりに、新しい小道具が入ってくるときにそれらを修正します(コンポーネント自体でのみ使用される派生データを作成します)。

var SampleComponent = React.createClass({
    mixins: [Reflux.ListenerMixin],

    // reusable helper function to build state object
    buildStateFromProps: function(props) {
        return {
            actualHeight: props.height + 20
        }
    },

    // default props if no such was set by a parent component
    getDefaultProps: function() {
        return {
            height: 100
        };
    },

    // initial state with all value set to something default
    // even using buildStateFromProps with default props
    getInitialState: function() {
        // this.props is built before this.state
        var state = buildStateFromProps(this.props);
        // append default data from store
        state.text = '';
    },

    // happens when the parent component send different 
    // props data
    componentWillReceiveProps: function(nextProps) {
        // building derivative data from new props
        // reusing buildStateFromProps
        this.setState(buildStateFromProps(nextProps));
    },

    // setting up store to be used by the component
    componentDidMount: function() {
        // this.listenTo is a helper function ListenerMixin
        this.listenTo(sampleStore, sampleUpdated);
    },

    // is called from the sampleStore update
    sampleUpdated: function(sampleData) {
        this.setState({
            text: sampleData.text
        });
    },

    render: function() {
        return (
            // ... 
            // using this.state.text from store updates and
            // this.state.height from prop updates
        );
    }
});

小道具データを状態に送信する理由は、レンダリング機能が乱雑にならないようにするためです。そうしないと、レンダリング関数には、コンポーネントの「レンダリング」に実際には関係のない多くのコードが含まれます。さらに、この派生データがアプリケーションの他の部分で使用されている場合、コンポーネントから引き出してストアに格納するのは簡単です。

お役に立てれば。

5
Spoike

この質問に対する有効な回答は、前の回答に対するコメントに隠されています。

@idolizeでは、Reactコンテキスト(隠された、まだ公式には文書化されていない機能)を使用してストアを渡すこともできます。コンテキストに関する記事がいくつかありますので、オンラインで検索してください!-Andy 15年7月17日18:41に

1
UKM