25

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

Flux / React のドキュメントと例の両方で、推奨される解決策として setState が示されているようですが、職場の数人の同僚と興味深い会話をして、他の誰かがこれに出くわしたのではないかと思いました。

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

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

React の「方法」に従えば、子コンポーネントではなく、状態がストアによって管理されることを期待していたでしょう。

私たちが考えた解決策は、最上位コンポーネントのすべてのストアを (props として) 取得し、必要に応じてそれらを子コンポーネントに渡すことです。しかし、それはすぐにかなり醜くなります。

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

4

4 に答える 4

43

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

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

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

動作プロパティ以外に、ステートフル コンポーネントはアップストリーム プロパティ経由で実際のデータを受け取りません。

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

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

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

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

于 2014-08-24T00:17:10.067 に答える
5

ストア データをコンポーネントの状態に置く方が理にかなっています。これは、 props が親コンポーネントによって変更される可能性があるためcomponentWillReceivePropsです。stateそのため、 wheneverを更新することは理にかなっています。

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

以下は、還流ストアと props の変更をリッスンして更新するサンプル コンポーネントです。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
        );
    }
});

props データを state に送信する理由は、render 関数が煩雑になるのを避けるためです。そうしないと、render 関数には、コンポーネントの「レンダリング」に実際には関係のない多くのコードが含まれます。さらに、この派生データがアプリケーションの他の部分で使用されている場合、コンポーネントから簡単に取り出してストアに入れることができます。

お役に立てれば。

于 2014-08-25T08:35:18.770 に答える
1

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

@idolize React コンテキストを使用してストアを渡すこともできます (非表示の、まだ公式に文書化されていない機能)。階層を下に渡すすべてのことを行う必要がないので、これは本当に素晴らしいことです。コンテキストに関する記事がいくつかあります。オンラインで検索してください。— アンディ

于 2016-02-06T21:29:01.070 に答える