【问题标题】:How to handle multiple checkboxes in a React Component如何处理 React 组件中的多个复选框
【发布时间】:2020-03-26 05:34:16
【问题描述】:

我有一个 React 组件,它循环遍历数据数组并为数组中的每个对象呈现一个复选框。

"supplies": [{
    "deviceName": "OMEGAX d3241",
    "productName": "ZA1239",
    "productGroup": "hearing aid batteries",
    "productId": "1",
    "lastOrderDate": "2020-01-01",
    "nextAvailabilityDate": "2020-09-01",
    "quantity": 60
  },
  {
    "productGroup": "hearing aid accessories",
    "productId": "3",
    "availableForReorder": true,
    "lastOrderDate": "2019-06-30",
    "nextAvailabilityDate": "2019-12-15",
    "quantity": 10,
    "size": "6mm"
  },
  {
    "productName": "DOME",
    "productGroup": "hearing aid accessories",
    "productId": "4",
    "availableForReorder": true,
    "lastOrderDate": "2019-06-30",
    "nextAvailabilityDate": "2019-12-15",
    "quantity": 10,
    "size": "7mm"
  },
  {
    "productName": "WaxBuster Single Unit",
    "productGroup": "hearing aid accessories",
    "productId": "5",
    "availableForReorder": true,
    "lastOrderDate": "2019-06-30",
    "nextAvailabilityDate": "2019-12-15",
    "quantity": 10
  }
]

大部分数据显示在 React 类组件

class SelectArrayItemsWidget extends React.Component {
  state = {
    checkedSupplies: new Map(),
  };
  componentDidMount() {
    this.props.getReOrderBatteryAndAccessoriesInformationData();
  }

  handleChecked = e => {
    const supply = e.target.name;
    const isChecked = e.target.checked;
    this.setState(prevState => ({
      checkedSupplies: prevState.checkedSupplies.set(supply, isChecked),
    }));
  };

  render() {
    const { supplies } = this.props;
    const { isChecked, checkedSupplies } = this.state;

    return supplies.map(supply => (
      <div key={supply.productId} className="order-background">
        <p className="ds-u-font-size--md ds-u-font-weight--bold">
          {supply.productName}
        </p>
        <div className="ds-u-border-left--10px ds-u-border-color--primary-alt">
          <div className="usa-alert-body mdot-alert-body">
            <p className="ds-u-margin--1px">
              <span className="ds-u-font-weight--bold">Battery: </span>
              {supply.productId}
            </p>
            <p className="ds-u-margin--1px">
              <span className="ds-u-font-weight--bold">Quantity: </span>
              {supply.quantity} <br />
              Approximately {supply.quantity} months supply
            </p>
            <p className="ds-u-margin--1px">
              <span className="ds-u-font-weight--bold">Last order date: </span>{' '}
              {moment(supply.lastOrderDate).format('MM/DD/YYYY')}
            </p>
          </div>
        </div>
        <div
          className={
            !isChecked
              ? 'ds-u-background-color--white ds-u-color--link-default button-dimensions ds-u-border-color--primary ds-u-border--2px'
              : 'ds-u-background-color--primary button-dimensions ds-u-color--white ds-u-border-color--primary ds-u-border--2px'
          }
        >
          <input
            name={supply.productId}
            checked={!checkedSupplies.get(supply.productId)}
            type="checkbox"
            onChange={this.handleChecked}
          />
          <label htmlFor={supply.productId} className="main">
            Order batteries for this device
          </label>
        </div>
      </div>
    ));
  }
}

我希望每个复选框的包装 div 更改文本颜色和背景颜色,具体取决于是否选中了单个复选框。我在容器上运行一个条件: !isChecked ? 'vads-u-background-color--white vads-u-color--link-default button-dimensions vads-u-border-color--primary vads-u-border--2px' : 'vads-u-background-color--primary button-dimensions vads-u-color--white vads-u-border-color--primary vads-u-border--2px'

但是,每次选中复选框时,容器都不会更改其样式属性。

【问题讨论】:

  • 我认为这里的主要问题是 state.checkedSupplies 是 Map 的实例,而 Map.prototype.set 始终返回相同的映射,即在执行突变后引用自身。 React 运行时比较先前和当前状态,发现两者相等,因此不会更新 DOM。要解决此问题,请考虑使用普通对象而不是 Map,或者可能仍使用 Map 但将其更新设为不可变操作。
  • 如果你想使用不可变版本的MapSet 等,还有不可变的 (immutable-js.github.io/immutable-js)。不过,它是一个大包。

标签: javascript html css reactjs


【解决方案1】:

这是问题的答案。

首先,我在全局状态中创建了一个 selectedItems 数组。

然后我更改了handleChecked onChange 方法,将复选框添加到selectedItems 数组中。

然后任何selectedItemschecked 并且具有productIdcheckbox container 的样式将会改变。

查看完整代码:

class SelectArrayItemsWidget extends React.Component {
  state = {
    selectedItems: [],
  };
  componentDidMount() {
    this.props.getReOrderBatteryAndAccessoriesInformationData();
  }

  handleChecked = e => {
    e.persist();
    if (e.target.checked) {
      this.setState(prevState => ({
        selectedItems: prevState.selectedItems.concat(e.target.name),
      }));
    } else {
      this.setState(prevState => ({
        selectedItems: prevState.selectedItems.filter(i => i !== e.target.name),
      }));
    }
  };

  render() {
    const { supplies } = this.props;
    const { selectedItems } = this.state;

    return supplies.map(supply => (
      <div key={supply.productId} className="order-background">
        <p className="vads-u-font-size--md vads-u-font-weight--bold">
          {supply.productName}
        </p>
        <div className="vads-u-border-left--10px vads-u-border-color--primary-alt">
          <div className="usa-alert-body mdot-alert-body">
            <p className="vads-u-margin--1px">
              <span className="vads-u-font-weight--bold">Battery: </span>
              {supply.productId}
            </p>
            <p className="vads-u-margin--1px">
              <span className="vads-u-font-weight--bold">Quantity: </span>
              {supply.quantity} <br />
              Approximately {supply.quantity} months supply
            </p>
            <p className="vads-u-margin--1px">
              <span className="vads-u-font-weight--bold">
                Last order date:{' '}
              </span>{' '}
              {moment(supply.lastOrderDate).format('MM/DD/YYYY')}
            </p>
          </div>
        </div>
        <div
          className={
            selectedItems.includes(supply.productId)
              ? 'vads-u-background-color--primary button-dimensions vads-u-color--white vads-u-border-color--primary vads-u-border--2px'
              : 'vads-u-background-color--white vads-u-color--link-default button-dimensions vads-u-border-color--primary vads-u-border--2px'
          }
        >
          <input
            name={supply.productId}
            type="checkbox"
            onChange={this.handleChecked}
          />
          <label htmlFor={supply.productId} className="main">
            Order batteries for this device
          </label>
        </div>
      </div>
    ));
  }
}

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 2022-01-14
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 2017-03-31
    • 2021-03-10
    • 2021-03-11
    • 2015-10-01
    相关资源
    最近更新 更多