React Array.map渲染子组件 setState更新后子组件未重渲染问题

问题根因
你的.map遍历写法和key设置没有问题,bug出在子组件复选框读取选中状态的逻辑完全写错了:
- 你在
TableRow组件里给复选框写的checked={selectedList.id},永远只会读取selectedList对象下名为id的固定属性,也就是你初始状态里塞的 dummy 值id:0 - 所有行的复选框都在读同一个固定属性值,根本没有读取当前行对应
id在selectedList里存储的0/1状态,哪怕父组件已经把所有业务id的选中状态更新为1,子组件读到的永远是固定的0,自然不会触发勾选状态更新。
修复步骤
1. 修正子组件复选框的取值逻辑
把TableRow里复选框的checked属性改为读取当前行id对应的状态值,同时把数字值转成布尔值适配表单属性要求:
function TableRow({ data, selectedList, setSelectedList }) { const { id, name, branch, address, phone, mail } = data function handleChange() { setSelectedList(prev => { return { ...prev, [id]: 1 ^ prev[id] } }) } return <tr> <th> <label> <input type="checkbox" className="checkbox checkbox-secondary" // 修正:读取当前行id对应的状态,转布尔值 checked={!!selectedList[id]} onChange={handleChange} /> </label> </th> <td> <div className="flex items-center space-x-3"> <div> <div className="font-bold">{name}</div> <div className="text-sm opacity-50">{branch}</div> </div> </div> </td> <td>{address}</td> <td>{phone}</td> <td>{mail}</td> </tr> }
2. 优化父组件初始状态,移除冗余dummy值
你之前加id:0是为了规避空对象读属性返回undefined导致的「非受控转受控组件」警告,完全没必要留这个冗余字段,初始化时直接根据列表数据生成默认全未选中的状态即可:
export default function Table() { const [selectAll, setSelectAll] = useState(false) // 初始化直接生成所有条目的默认未选中状态,从根源避免undefined问题 const initialSelected = {} dataList.forEach(ele => initialSelected[ele.id] = 0) const [selectedList, setSelectedList] = useState(initialSelected) useEffect(()=>{ let newSelectedList = {} if(selectAll){ dataList.forEach(ele => newSelectedList[ele.id]=1); }else{ dataList.forEach(ele => newSelectedList[ele.id]=0); } setSelectedList(newSelectedList) },[selectAll]) // 其余渲染逻辑保持不变 return <div> <ActionBar /> <div className="overflow-x-auto w-full"> <table className="table w-full"> <thead> <TableHeadingRow select selectAll={selectAll} setSelectAll={setSelectAll} /> </thead> <tbody> { dataList.map(data => <TableRow key={data.id} data={data} selectedList={selectedList} setSelectedList={setSelectedList} />) } </tbody> <tfoot> <TableHeadingRow /> </tfoot> </table> </div> </div> }
改完后点击全选按钮时,selectedList更新后每一行的子组件都能正确读到自身id对应的选中状态,自动触发重渲染完成全选/取消全选效果。
内容的提问来源于stack exchange,提问作者prithvi2k2
相关产品推荐
相关产品推荐

