You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript数组与React组件状态更新冲突问题排查

问题根源

departmentArray是定义在组件函数内部的普通局部变量,只要组件触发重渲染,这行let departmentArray = ([]);就会重新执行,直接把数组重置为空数组,之前存入的选中值会全部丢失。
保留状态更新代码时,点击复选框会调用setXxxCheck触发组件重渲染,数组被重置,自然无法正常记录选中值;删掉状态更新代码后,点击操作不会触发组件重渲染,局部变量不会被重置,所以数组的增删操作看起来是正常的——这只是没有触发重渲染带来的假象,并不是代码逻辑本身正确。

除此之外原写法还有两个明显问题:

  • 直接用push/splice修改原数组属于可变数据操作,不符合React状态更新的不可变要求
  • 同时维护三个独立的复选框布尔状态、一个选中部门数组,属于同源数据重复存储,非常容易出现数据不一致的问题
修复方案

把选中部门列表也纳入React状态管理,用单一数据源维护所有选中状态,不需要额外维护三个单独的布尔值,代码更简洁也不会出现状态不同步的问题:

import { useState } from 'react';
import { Form } from 'react-bootstrap';

function DepartmentSelector() {
  // 仅用一个状态存储所有选中的部门
  const [departmentArray, setDepartmentArray] = useState([]);

  function handleCheck(val) {
    setDepartmentArray(prevSelected => {
      const index = prevSelected.indexOf(val);
      if (index > -1) {
        // 已选中则过滤掉当前值,返回新数组
        return prevSelected.filter(item => item !== val);
      } else {
        // 未选中则把当前值加入新数组
        return [...prevSelected, val];
      }
    })
  }

  return (
    <>
      <Form.Check 
        name="department" 
        onClick={() => handleCheck("Maintenance")} 
        checked={departmentArray.includes("Maintenance")} 
      />
      <Form.Check 
        name="department" 
        onClick={() => handleCheck("Process")} 
        checked={departmentArray.includes("Process")} 
      />
      <Form.Check 
        name="department" 
        onClick={() => handleCheck("Toolroom")} 
        checked={departmentArray.includes("Toolroom")} 
      />
    </>
  )
}

修复后所有和选中相关的状态都存在React state中,重渲染时状态不会丢失,所有复选框的选中状态直接从同一个数组派生,不会出现数据冲突。

内容的提问来源于stack exchange,提问作者Nathan Field

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:36:10