【问题标题】:How to manage state with checkboxes in React?如何在 React 中使用复选框管理状态?
【发布时间】:2016-12-15 16:52:57
【问题描述】:

我是 React 的新手,我正在尝试制作一个用户表,并希望使用复选框来管理他们的权限。单击复选框时,我遇到了更新状态的问题。 handleChange 方法是我遇到问题的地方。我不知道如何确定正确的复选框以更改该特定用户的状态。我在想也许我需要为每个人添加一个 id 道具,但这似乎对于大量用户来说可能会失控,即每个用户的每个权限都有一个 id。我觉得这应该不是那么难,但我已经卡了很长时间了。

我的组件代码如下。

import React from 'react'
import {Link} from 'react-router'
import {Panel, Button, PageHeader, Row, Col, Table, Input} from 'react-bootstrap'


export class UserPermissions extends React.Component {

constructor() {
    super();
    this.state = {
        users: [
            {   
                name: 'Jerry',
                viewAccounts: true,
                modifyAccounts: true,
                viewUsers: false,
                modifyUsers: true
            },
            {   
                name: 'George',
                viewAccounts: false,
                modifyAccounts: true,
                viewUsers: false,
                modifyUsers: false
            },
            {   
                name: 'Elaine',
                viewAccounts: true,
                modifyAccounts: false,
                viewUsers: false,
                modifyUsers: true
            }
    ]
    }               
}   

handleChange(e){
  //not sure how to write this
}

renderHeadings(data){
    return data.map((step, index) => <th key={index} style={{align:"center"}}>{step}</th>);

}

renderRows(data){
    return data.map((step, index) => 
            <tr key={index}>
                <td>{step['name']}</td>
                <td style={{align:"center", paddingLeft:"40px"}}>
                    <Input type="checkbox"
                           checked={step['viewAccounts']} 
                           onChange={this.handleChange}/></td>
                <td style={{align:"center", paddingLeft:"40px"}}>
                    <Input type="checkbox"
                           checked={step['modifyAccounts']} 
                           onChange={this.handleChange}/></td>
                <td style={{align:"center", paddingLeft:"40px"}}>
                    <Input type="checkbox"
                           checked={step['viewUsers']} 
                           onChange={this.handleChange}/></td>
                <td style={{align:"center", paddingLeft:"40px"}}>
                    <Input type="checkbox"
                           checked={step['modifyUsers']}
                           onChange={this.handleChange} /></td>
                <td style={{align:"center"}}>
                    <Link to="/users"><i className="fa fa-edit fa-2x fa-fw" /></Link>
                    <Link to="/users"><i className="fa fa-times-circle fa-2x fa-fw" /></Link></td>
            </tr>
    );

}

render() {
    return (
        <div>
             <Row>
                <Col lg={12}>
                    <PageHeader>User Permissions</PageHeader>
                </Col>

                <Col lg={12}>
                    <Panel header={<span>Users</span>} bsStyle="primary">
                        <div>
                            <div className="dataTable_wrapper">
                                <div id="dataTables-example_wrapper" className="dataTables_wrapper form-inline dt-bootstrap no-footer">
                                    <Row>
                                        <Col sm={12}>
                                            <Table striped condensed responsive>
                                                <thead>
                                                <tr>
                                                    {this.renderHeadings(this.props.headings)}
                                                </tr>
                                                </thead>
                                                <tbody>
                                                    {this.renderRows(this.state.users)}
                                                </tbody>
                                            </Table>
                                        </Col>
                                    </Row>
                                </div>
                            </div>
                        </div>
                    </Panel>
                    <Button bsStyle="success">Add User</Button>
                </Col>
            </Row>
        </div>
        );
}
}

UserPermissions.propTypes = {
headings: React.PropTypes.array
}

UserPermissions.defaultProps = {
headings: ['Name', 'View Accounts', 'Modify Accounts', 'View Users', 'Modify Users']

}

【问题讨论】:

  • 调用句柄更改,步长值如下:this.handleChange('modifyUsers') 或者您可以使用refs 来识别复选框。

标签: javascript user-interface reactjs checkbox web-frontend


【解决方案1】:

首先,您应该为每个用户添加id。按姓名识别用户是一种不好的做法:

constructor() {
  super();
  this.state = {
    users: [
      {   
        id: 1,
        name: 'Jerry',
        viewAccounts: true,
        modifyAccounts: true,
        viewUsers: false,
        modifyUsers: true
      },
      { 
        id: 2,  
        name: 'George',
        viewAccounts: false,
        modifyAccounts: true,
        viewUsers: false,
        modifyUsers: false
      },
      {   
        id: 2,
        name: 'Elaine',
        viewAccounts: true,
        modifyAccounts: false,
        viewUsers: false,
        modifyUsers: true
      }
    ]
  }               
}

接下来,您应该提供给this.handleChange函数id的用户,name我们正在更改的属性,以及当前value

renderRows(data) {
  return data.map((step, index) => 
    <tr key={index}>
      <td>{step['name']}</td>
      <td style={{align:"center", paddingLeft:"40px"}}>
        <Input type="checkbox"
          checked={step['viewAccounts']} 
          onChange={e => this.handleChange(step.id, 'viewAccounts', step['viewAccounts'])}/></td>
      <td style={{align:"center", paddingLeft:"40px"}}>
        <Input type="checkbox"
          checked={step['modifyAccounts']} 
          onChange={e => this.handleChange(step.id, 'modifyAccounts', step['modifyAccounts'])}/></td>
      <td style={{align:"center", paddingLeft:"40px"}}>
        <Input type="checkbox"
          checked={step['viewUsers']} 
          onChange={e => this.handleChange(step.id, 'viewUsers', step['viewUsers'])}/></td>
      <td style={{align:"center", paddingLeft:"40px"}}>
        <Input type="checkbox"
          checked={step['modifyUsers']}
          onChange={e => this.handleChange(step.id, 'modifyUsers', step['modifyUsers'])}/></td>
      <td style={{align:"center"}}>
        <Link to="/users"><i className="fa fa-edit fa-2x fa-fw" /></Link>
        <Link to="/users"><i className="fa fa-times-circle fa-2x fa-fw" /></Link></td>
    </tr>
  );
}

最后,在this.handleChange 函数中,我们应该根据给定的值更新特定的用户数据:

handleChange(id, name, value) {
  this.setState({
    users: this.state.users.map((user) => {
      if (user.id !== id) return user;

      // `Object.assign` function is used to return new modified object.
      return Object.assign({}, user, {
        // We should assign opposite to `value` variable value, as we are toggling permissions.
        [name]: !value
      });
    });
  });
}

【讨论】:

  • 感谢您的快速回复。我尝试了您的建议,但效果不佳。如果权限的状态为真,它将设置为假,但不会将假设置为真。我在 handleChange 中添加了console.log(value),无论是否选中该框,它都会输出“on”。我正在努力找出原因。
  • 我将所有权限的checked={step['viewAccounts']} 更改为value={step['viewAccounts']},现在它可以正常工作了。再次感谢您的帮助!
  • 实际上我所做的并没有正确修复它。重新加载时,复选框与打开或关闭的权限不匹配,它们现在只是显示为空白,因为它们不再具有选中的属性。
  • @JamesThibaudeau,好的,让我们试着弄清楚。首先,每个输入都应该有对应的checked 属性。您不应该为所有输入设置value={step['viewAccounts']}。您需要返回输入的值作为答案。另外,我犯了一个错误,而不是e.target.value,您还应该向onChange 函数提供来自状态的相应值。检查更新的答案,现在它是正确的。
  • 这是有道理的。进行更改可以正确设置状态并显示视图。感谢您的帮助!
【解决方案2】:

查看该库的源代码,了解它们如何管理复选框的状态。也许您甚至可以根据需要使用它:

https://www.npmjs.com/package/react-checkbox-group

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-17
    • 2020-03-18
    • 2023-01-17
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多