46

データ構造用のシンプルなグリッドベースのエディターを作成しようとしていますが、React.js で概念的な問題がいくつかあります。彼らのドキュメントはこれに関してあまり役に立たないので、ここの誰かが助けてくれることを願っています.

まず、外部コンポーネントから内部コンポーネントに状態を転送する正しい方法は何ですか? 内部コンポーネントの状態変化を外部コンポーネントに「バブルアップ」させることは可能ですか?

第 2 に、2 つの別個のコンポーネントでデータを共有して、一方の変更を他方に表示することはできますか?

以下は、私がやりたいことの簡単な例です ( JSFiddle バージョン):

companyオブジェクトの配列を含むオブジェクトがありますemployeeemployeeリストを編集可能なグリッドにレイアウトしたい。ボタンをクリックすると、結果のcompanyオブジェクトとミューテーション (コンソールへの書き込み) が表示されます。

/** @jsx React.DOM */

var Cell = React.createClass({
    getInitialState: function () {
        return {data: ""};
    },

    componentWillMount: function () {
        this.setState({data: this.props.data});
    },
    onChange: function (evt) {
        console.log(this.state, evt.target.value);
        this.setState({data: evt.target.value});
    },
    render: function () {
        var data = this.props.data;
        return <input value={this.state.data} onChange={this.onChange} />
    }
});

var Row = React.createClass({
    render: function () {
        return (<div className="row">
            <Cell data={this.props.data.name} />
            <Cell data={this.props.data.location} />
            <Cell data={this.props.data.phone} />
        </div>);
    }
});

var Grid = React.createClass({
    render: function () {
        var rows = this.props.data.map(function (rowData, index) {
            return <Row key={index} data={rowData}>Row</Row>;
        });
        return <div className="table">{rows}</div>;
    }
});

var Button = React.createClass({
    getInitialState: function () {
        return {data: {}}
    },
    componentWillMount: function () {
        this.setState({data: this.props.data});
    },
    onClick: function () {
        console.log(this.state);
    },
    render: function () {
        return <button onClick={this.onClick}>Update</button>;
    }
});

var company = {
    name: "Innotech",
    employees: [
        {id: "1", name: "Peter", location: "IT", phone: "555-1212"},
        {id: "2", name: "Samir", location: "IT", phone: "555-1213"},
        {id: "3", name: "Milton", location: "loading dock", phone: "none"}
    ]
};


React.renderComponent(
    <div><Grid data={company.employees} /><Button data={company} /></div>,       
    document.getElementById('employees')
);
4

3 に答える 3

52

これは、現在 React で最も文書化されていない部分だと思います。コンポーネント間で通信するための推奨される方法は、親から子への通信時に props を設定し、子から親への通信時に props を介してコールバックを渡すことです。

兄弟コンポーネント間でデータを共有したい場合は、状態を管理し、それを両方のコンポーネントに渡す親コンポーネントが必要であることを意味します。ほとんどの場合、状態はコンポーネント階層の最上位付近に存在し、各情報は (多くても) 1 つのコンポーネントの状態に存在する必要があります。

詳細については、Pete Hunt のブログ投稿Thinking in Reactを参照してください。


これを念頭に置いて、あなたのfiddleを更新しました。

Grid独自の状態を維持しないように変更しましたが、代わりに小道具を介して渡されたデータを常に表示し、親からデータの変更を要求onCellChangeしたい場合は小道具から呼び出します。(コンポーネントは、その親が変更されたデータでグリッドのプロップを更新することを期待します。親が拒否した場合 (おそらくデータ検証の失敗などにより)、読み取り専用グリッドになります。)Griddata

Editorまた、グリッドとその兄弟ボタンをラップする新しいコンポーネントを作成したことにも気付くでしょう。コンポーネントはEditor基本的にページ全体を管理します。実際のアプリでは、グリッドのコンテンツが別の場所で必要になる可能性が高いため、状態が上位に移動します。あなたのコンポーネントはネイティブタグButton以上のことをしていなかったので削除しました。<button>私は去りCellましたが、それも削除できました-タグを直接Row簡単に使用できました。<input>

これが理にかなっていることを願っています。不明な点は遠慮なく聞いてください。これについてもっとチャットしたい場合は、通常、 #reactjs IRC ルームにも人がいます。

于 2013-12-27T06:57:11.877 に答える
0

親コンポーネントが意味をなさない場合に兄弟コンポーネント間でデータを共有する別の方法は、コンポーネント間でイベントを使用することです。たとえば、Backbone.Events、ブラウザに移植された Node.js Emitter、または同様のライブラリを使用できます。リアクティブ ストリームが必要な場合は、Bacon.js を使用することもできます。ここに Bacon.js と React.js を組み合わせた素晴らしいシンプルな例があります: http://joshbassett.info/2014/reactive-uis-with-react-and-bacon/

于 2014-06-04T16:02:25.323 に答える