React (Facebook): managed state of controlled checkboxes

后端 未结 2 488
执笔经年
执笔经年 2020-12-14 01:05

I\'m having a little problem while trying to create a checkbox that selects and deselects other individual checkboxes (select/deselect all) with React. I\'ve read http://fac

相关标签:
2条回答
  • 2020-12-14 01:43

    If you are dealing with checkboxes you can use the checkedLink attribute. Here is another possible implementation, that makes the global checkbox controlled (instead of uncontrolled in the current answers):

    JsFiddle

    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>
            );
        },
    
    });
    

    It is simpler to use checkedLink=this.linkState("checkboxValue") with LinkedStateMixin if the state to mutate is not deeply nested (like this is the case in this question)

    Edit: checkedLink and valueLink are being deprecated but were recommmended in previous versions of React.

    0 讨论(0)
  • 2020-12-14 02:05

    In your render function, the scope of this for the checks mapping function is different from render, which is the scope you need for __changeSelection, so this.__changeSelection won't locate a __changeSelection property. If you add a .bind(this) to the end of that mapping function, you can bind it's scope to the same this as render:

    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));
    

    On a side note, I would just pass the id to the handler function instead of assigning data-attributes. This will remove the need to locate that element in your handler:

    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));
    

    Then update your __changeSelection function to pass in the id as the first arg and remove the attribute lookup line:

    __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 });
    
    }
    

    Here is an example of it all put together, along with a jsfiddle for you to try it out:

    /** @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'));
    
    0 讨论(0)
提交回复
热议问题