React中无法更新嵌套数组元素state的解决方法
问题根因
你的代码存在5个核心错误,直接导致状态更新失效、数据结构错乱:
- 接口请求直接写在组件函数体内,组件每次重渲染都会重复触发请求,造成无限重渲染循环
changeValue里的状态更新逻辑完全错误:map遍历时不匹配的项没有返回原内容,匹配项的更新逻辑错误拼接了整个旧列表,还额外给结果多套了一层数组,直接把原本的二维数组结构改坏- 单选框触发change事件时调用了
event.preventDefault(),会阻止单选框本身的默认选中行为 - 提交按钮是
submit类型,点击时没有阻止表单默认提交行为,会触发页面刷新,所有内存中的状态直接清空 - JSX中label的
for属性不符合React语法要求,需要写成htmlFor,否则会抛出控制台警告
修正步骤
- 把GET接口请求放到
useEffect钩子中,配置空依赖数组,保证只在组件首次挂载时执行一次,避免重复请求 - 重写
changeValue的状态更新逻辑:遍历列表时,非匹配项直接原样返回,匹配到对应name的项时,保留前两个字段,把第三个binary字段替换为当前选中的value,使用函数式更新避免闭包拿到旧状态值导致更新异常 - 移除change事件里的
event.preventDefault(),不要干预单选框的原生交互逻辑 - 给表单提交事件加默认行为阻止,避免页面刷新
- 把label的
for属性替换为htmlFor,符合React的JSX语法规范
修正后的完整代码
import React, { useState, useEffect } from "react"; import Axios from "axios"; function Attendance() { const [attedanceList, setAttedanceList] = useState([]); // 接口请求移到useEffect,仅组件首次挂载时执行 useEffect(() => { Axios.get("http://localhost:9000/attendance").then((response) => { setAttedanceList(response.data.data.values); }); }, []); function changeValue(event) { const { name, value } = event.target; // 函数式更新,规避闭包旧值问题 setAttedanceList(prevList => prevList.map(items => { // 匹配到当前修改的用户行,替换第三个binary值,其余字段保持不变 if (items[0] === name) { return [items[0], items[1], value]; } // 非匹配行直接原样返回 return items; }) ); } function sendAllValues(event) { // 阻止表单默认提交导致的页面刷新 event.preventDefault(); Axios.post("http://localhost:9000/attendance", { attedanceList }); } return ( <form onSubmit={sendAllValues}> {attedanceList.map((val, index) => { // 跳过第一行表头数据 if (index !== 0) { const presentId = `present${index}`; const absentId = `absent${index}`; return ( <div key={index}> <div> {val[0]} {val[1]} <input type="radio" id={presentId} name={val[0]} value="1" checked={val[2] === "1"} onChange={changeValue} /> <label htmlFor={presentId}>Present</label> <input type="radio" id={absentId} name={val[0]} value="0" checked={val[2] === "0"} onChange={changeValue} /> <label htmlFor={absentId}>Absent</label> </div> </div> ); } return null; })} <button type="submit"> Submit </button> </form> ); } export default Attendance;
效果说明
- 修正后每次点击单选框,只会更新对应用户行的binary值,其余行数据完全不受影响
- 状态更新后单选框的
checked属性会自动和最新状态同步,选中状态不会错乱 - 提交时直接取最新的
attedanceList传给后端即可,数据结构和接口初始返回的格式完全一致,不需要额外转换
内容的提问来源于stack exchange,提问作者user16704275
相关产品推荐
相关产品推荐

