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

React代码首次渲染正常,页面重渲染时崩溃的问题排查

问题:页面重渲染时筛选复选框功能崩溃,首次渲染正常

问题背景

基于以下筛选选项对象实现复选框筛选功能:

const filterOptions = {
    'size': ['s', 'm', 'l'],
    'color': ['black', 'white', 'pink', 'beige'],
    'fit': ['relaxed fit','slim fit', 'skinny fit', 'oversize'],
    'pattern': ['patterned', 'spotted', 'solid color'],
    'material': ['wool', 'cotton', 'leather', 'denim', 'satin']
}

核心逻辑是通过checkedValue状态对象存储每个筛选值的选中状态,首次渲染时功能正常,但页面重渲染时抛出错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'checked')

相关核心代码如下:

  • 状态初始化与初始化逻辑:
const [checkedValue, setCheckedValue] = useState({})

useEffect(() => {
  const filterValuesArray = Object.values(filterOptions).flat()
  filterValuesArray.map(filter => setCheckedValue(currentState => ({...currentState, [filter]: { ...currentState[filter], checked: false }})))
}, [])
  • 复选框渲染:
<div className='popper'>
  {filterValue.map(value => {
    return (
      <div key={`${value}`} className='popper-item'>
        <label className='popper-label'>{value}</label>
        <input onChange={handleCheckbox} checked={checkedValue[value].checked} type='checkbox' value={value} className="popper-checkbox" />
      </div>
    )}
  )}
</div>
  • 复选框 onChange 处理:
const handleCheckbox = (event) => {
const value = event.target.value;
setCheckedValue({...checkedValue, [value]: { ...checkedValue[value], checked: !checkedValue[value].checked }})
if(activeFilters.includes(value)) {
  const deleteFromArray = activeFilters.filter(item => item !== value)
  setActiveFilters(deleteFromArray)
} else {
  setActiveFilters([...activeFilters, value])
}}

错误根源分析

  1. useEffect 依赖缺失:子组件中初始化checkedValue的useEffect依赖为空数组,仅在组件首次挂载时执行。当页面重渲染(如父组件更新、Context状态变化)时,若checkedValue被重置或未包含当前筛选值,就会出现checkedValue[value]为undefined的情况,触发读取checked属性的错误。
  2. 状态更新未使用函数式更新:handleCheckbox中直接依赖checkedValue的快照更新状态,React状态更新是异步的,多次快速操作可能导致状态不一致或丢失。
  3. 初始化逻辑低效:循环调用setCheckedValue会触发多次状态更新,引发不必要的组件重渲染,也可能导致状态初始化不完整。

修复方案

1. 完善初始化逻辑与useEffect依赖

将filterOptions加入useEffect依赖,确保筛选选项变化时重新初始化;同时通过reduce一次性构建完整的初始化对象,避免多次状态更新:

useEffect(() => {
  const initialCheckedValue = Object.values(filterOptions).flat().reduce((acc, filter) => {
    acc[filter] = { checked: false };
    return acc;
  }, {});
  setCheckedValue(initialCheckedValue);
}, [filterOptions, setCheckedValue]);

2. 使用函数式更新处理状态

在handleCheckbox中,使用函数式更新获取最新状态,避免异步更新导致的快照问题:

const handleCheckbox = (event) => {
  const value = event.target.value;
  
  // 函数式更新checkedValue
  setCheckedValue(prevState => ({
    ...prevState,
    [value]: { ...prevState[value], checked: !prevState[value].checked }
  }));
  
  // 同样用函数式更新activeFilters
  setActiveFilters(prevFilters => {
    if (prevFilters.includes(value)) {
      return prevFilters.filter(item => item !== value);
    } else {
      return [...prevFilters, value];
    }
  });
};

3. 添加可选链兜底(避免临时报错)

在渲染复选框时,使用可选链和空值合并运算符,确保即使checkedValue[value]不存在也不会报错:

<input 
  onChange={handleCheckbox} 
  checked={checkedValue[value]?.checked ?? false} 
  type='checkbox' 
  value={value} 
  className="popper-checkbox" 
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 09:50:50