ReactJS:来自State的动态复选框

use*_*459 7 reactjs

我有一组动态的元素,所以我不知道该集合的内容是什么.我想动态渲染这些复选框,默认情况下都选中它们.您应该能够取消选中框,这会在渲染中触发另一个地图功能.(所以基本上是我的过滤器)

我在国家设置上苦苦挣扎.我想到了以下内容,我希望通过API调用在ComponentWillMount期间设置initialState:

scenario 1 (arrays): 

this.state {
    checkboxes: [value1, value2, value3],
    checkedcheckboxes: [value1, value2]
}
Run Code Online (Sandbox Code Playgroud)

然后我可以使用react.addons.update函数来更改checkcheckboxes状态.缺点是在渲染我的复选框时,我必须在每个复选框上使用indexOf循环检查checkcheckboxes数组以查看是否应该检查它.

scenario 2 (object):

this.state {
    checkboxes: {
       value1: true,
       value2: true,
       value3: false
}
Run Code Online (Sandbox Code Playgroud)

这样我有动态键,这使得它更难工作(我猜),因为我必须在我的setState中使用计算字段.我还认为这会对我的表现产生负面影响.

这种模式有没有最好的做法?

谢谢!

Mic*_*ker 19

我可能会将您的状态设置为包含一组对象(代表您的复选框),以及一个代表您的过滤器的字符串.每个复选框对象将包含两个属性,标签的文本和复选框的值.

对于您的初始状态,您希望此数组为空,然后在componentDidMount生命周期中,您将执行API调用并设置状态以包含您收到的信息.

constructor(props) {
    super(props);

    this.state = {
        checkboxes: [],
        filter: 'ALL'
    };

    //each checkbox would take the form of {label: 'some label', checked: true}
}

componentDidMount() {
    getData(response => { //some API call
        this.setState({
            checkboxes: response.body
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

为了让您的组件呈现这些复选框,它需要了解您的状态中的复选框对象与实际DOM元素的关系.您可以创建一个利用.map此功能的辅助函数.您还可以利用.filter将过滤器应用于您所在州的每个对象,并删除与您的过滤器不匹配的过滤器.

function renderCheckboxes() {
    const {checkboxes, filter} = this.state;

    return checkboxes
        .filter(checkbox =>
            filter === 'ALL' ||
            filter === 'CHECKED' && checkbox.checked ||
            filter === 'UNCHECKED' && !checkbox.checked
        )
        .map((checkbox, index) =>
            <div>
                <label>
                    <input
                        type="checkbox"
                        checked={checkbox.checked}
                        onChange={toggleCheckbox.bind(this, index)}
                    />
                    {checkbox.label}
                </label>
            </div>
        );
}
Run Code Online (Sandbox Code Playgroud)

注意每个复选框如何将onChange属性映射到某个函数?您需要将此提供给使用该checked属性呈现的每个复选框,因为您将创建一个受控组件,并且您的状态将控制是否检查每个单独的组件.您的toggleCheckbox功能可能如下所示:

function toggleCheckbox(index) {
    const {checkboxes} = this.state;

    checkboxes[index].checked = !checkboxes[index].checked;

    this.setState({
        checkboxes
    });
}
Run Code Online (Sandbox Code Playgroud)

创建一个将过滤器设置为不同字符串的函数也可能很有用:

function updateFilter(filter) {
    this.setState({
        filter
    });
}
Run Code Online (Sandbox Code Playgroud)

最后,您可以在函数中使用这些函数render来显示复选框以及更新过滤器状态的链接(我还添加了一些不间断的空格来分隔每个过滤器链接):

render() {
    return (
        <div>
            {renderCheckboxes.call(this)}
            <div>
                <h4>Filters ({this.state.filter})</h4>
                <a href="#" onClick={updateFilter.bind(this, 'ALL')}>ALL</a>
                &nbsp;|&nbsp;
                <a href="#" onClick={updateFilter.bind(this, 'CHECKED')}>CHECKED</a>
                &nbsp;|&nbsp;
                <a href="#" onClick={updateFilter.bind(this, 'UNCHECKED')}>UNCHECKED</a>
            </div>
        </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

以下是此工作的一个示例 - 减去API调用:

https://jsbin.com/bageyudaqe/edit?js,output

希望这可以帮助!