32

Reactを使用して、他の個々のチェックボックスを選択および選択解除する (すべて選択/選択解除する) チェックボックスを作成しようとすると、少し問題が発生します。http://facebook.github.io/react/docs/forms.htmlを読み、制御された sと制御されていない s の間に違いがあることを発見しまし<input>た。私のテストコードは次のとおりです。

var Test = React.createClass({
    getInitialState: function() {
        return {
            data: [
                { id: 1, selected: false },
                { id: 2, selected: false },
                { id: 3, selected: false },
                { id: 4, selected: false }
            ]
        };
    },
    render: function() {
        var checks = this.state.data.map(function(d) {
            return (
                <div>
                    <input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} />
                    {d.id}
                    <br />
                </div>
            );
        });
        return (
            <form>
                <input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector
                <br />
                {checks}
            </form>
        );
    },
    __changeSelection: function(e) {
        var id = e.target.getAttribute('data-id');
        var state = this.state.data.map(function(d) {
            return {
                id: d.id,
                selected: (d.id === id ? !d.selected : d.selected)
            };
        });

        this.setState({ data: state });

    },
    __changeAllChecks: function(e) {
        var value = this.refs.globalSelector.getDOMNode().checked;
        var state = this.state.data.map(function(d) {
            return { id: d.id, selected: value };
        });

        this.setState({ data: state });
    }
});

React.renderComponent(<Test />, document.getElementById('content'));

「グローバルセレクター」は期待どおりに機能します。選択すると、他のすべてのチェックが選択されます。問題は__changeSelection()、他のチェックボックスのいずれかがクリックされたときにハンドラーが起動されないことです。

この作業を行うための適切な方法が何であるかわかりません。React モデルは、この種の相互作用をモデル化するのに最適なモデルではないのでしょうか? どうすればよいですか?

前もって感謝します

4

2 に答える 2

43

あなたのrender関数ではthis、マッピング関数の のスコープは、 に必要なスコープである とchecksは異なるため、プロパティを見つけられません。そのマッピング関数の最後にa を追加すると、そのスコープを と同じにバインドできます。render__changeSelectionthis.__changeSelection__changeSelection.bind(this)thisrender

var checks = this.state.data.map(function(d) {
    return (
        <div>
            <input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} />
            {d.id}
            <br />
        </div>
    );
}.bind(this));

補足として、idデータ属性を割り当てる代わりに、ハンドラー関数に渡すだけです。これにより、ハンドラーでその要素を見つける必要がなくなります。

var checks = this.state.data.map(function(d) {
    return (
        <div>
            <input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} />
            {d.id}
            <br />
        </div>
    );
}.bind(this));

次に、最初の引数として を渡し、属性ルックアップ行を削除するように__changeSelection関数を更新します。id

__changeSelection: function(id) {
    var state = this.state.data.map(function(d) {
        return {
            id: d.id,
            selected: (d.id === id ? !d.selected : d.selected)
        };
    });

    this.setState({ data: state });

}

以下は、試してみるための jsfiddleとともに、すべてをまとめた例です。

/** @jsx React.DOM */

var Test = React.createClass({
    getInitialState: function() {
        return {
            data: [
                { id: 1, selected: false },
                { id: 2, selected: false },
                { id: 3, selected: false },
                { id: 4, selected: false }
            ]
        };
    },
    render: function() {
        var checks = this.state.data.map(function(d) {
            return (
                <div>
                    <input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} />
                    {d.id}
                    <br />
                </div>
            );
        }.bind(this));
        return (
            <form>
                <input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector
                <br />
                {checks}
            </form>
        );
    },
    __changeSelection: function(id) {
        var state = this.state.data.map(function(d) {
            return {
                id: d.id,
                selected: (d.id === id ? !d.selected : d.selected)
            };
        });

        this.setState({ data: state });

    },
    __changeAllChecks: function() {
        var value = this.refs.globalSelector.getDOMNode().checked;
        var state = this.state.data.map(function(d) {
            return { id: d.id, selected: value };
        });

        this.setState({ data: state });
    }
});

React.renderComponent(<Test />, document.getElementById('content'));
于 2014-02-05T19:14:11.363 に答える
3

チェックボックスを扱っている場合は、checkedLink属性を使用できます。これは、グローバルチェックボックスを制御する別の可能な実装です(現在の回答で制御されていないのではなく):

Jsフィドル

var Test = React.createClass({

    getInitialState: function() {
        return {
            globalCheckbox: false,
            data: [
                { id: 1, selected: false },
                { id: 2, selected: false },
                { id: 3, selected: false },
                { id: 4, selected: false }
            ]
        };
    },

    changeCheckForId: function(id,bool) {
        this.setState(
            {
            data: this.state.data.map(function(d) {
                var newSelected = (d.id === id ? bool : d.selected);
                return {id: d.id, selected: newSelected};
            }
        )});
    },

    changeCheckForAll: function(bool) {
        this.setState({
                globalCheckbox: true,
                data: this.state.data.map(function(d) {
                    return {id: d.id, selected: bool};
                })
        });
    },



    linkCheckbox: function(d) {
      return {
         value: d.selected,
         requestChange: function(bool) { this.changeCheckForId(d.id,bool); }.bind(this)
      };
    },

    linkGlobalCheckbox: function() {
      return {
         value: this.state.globalCheckbox,
         requestChange: function(bool) { this.changeCheckForAll(bool); }.bind(this)
      };
    },

    render: function() {
        var checks = this.state.data.map(function(d) {
            return (
                <div>
                    <input key={d.id} type="checkbox" checkedLink={this.linkCheckbox(d)} />
                    {d.id}
                    <br />
                </div>
            );
        }.bind(this));

        return (
            <form>
                <input type="checkbox" checkedLink={this.linkGlobalCheckbox()} />Global selector
                <br />
                {checks}
            </form>
        );
    },

});

checkedLink=this.linkState("checkboxValue")変更する状態が深くネストされていない場合は、使用する方が簡単ですLinkedStateMixin(この質問の場合のように)

編集:checkedLinkvalueLinkは非推奨ですが、以前のバージョンの React では推奨されていました。

于 2015-08-01T02:52:45.693 に答える