React循环调用useEffect仅触发最后一个效果的问题排查
问题分析与解决思路
问题根源
- React的
setState是异步批量执行的,在handleSelectAllClick的循环里,多次调用setCurrentrow会被合并处理,最终currentRow只会保留循环的最后一个元素。 - 你的
useEffect依赖checkboxStatus,每次数组更新都会触发,但此时currentRow已经被覆盖成最后一行,导致addMarkersToMap每次都只处理最后一行的数据,自然只有最后一项的标记被添加。
解决思路
1. 移除冗余的currentRow状态
不需要单独维护currentRow来传递行数据,直接通过checkboxStatus反向匹配选中的行,在useEffect里批量处理所有选中项:
const [checkboxStatus, setCheckboxStatus ] = useState([]); useEffect(() => { // 根据选中的ID筛选出对应的行 const selectedRows = props.rows.filter(row => { const chkId = `${props.window.tablename}_${row.id}_chk`; return checkboxStatus.includes(chkId); }); // 批量添加标记 selectedRows.forEach(row => addMarkersToMap(row)); }, [checkboxStatus, props.rows]);
2. 优化全选逻辑,一次性更新状态
不要在循环里多次调用setCheckboxStatus,直接生成所有选中ID的数组后一次性更新:
const handleSelectAllClick = (event) => { const allChkIds = props.rows.map(n => `${props.window.tablename}_${n.id}_chk`); setCheckboxStatus(allChkIds); };
3. 调整单选逻辑,保持状态一致性
单选时直接操作checkboxStatus数组,不需要再设置currentRow:
const handleCheckboxClick = (event, row) => { const chkId = `${props.window.tablename}_${row.id}_chk`; setCheckboxStatus(prevStatus => { if (prevStatus.includes(chkId)) { // 取消选中,移除对应ID return prevStatus.filter(id => id !== chkId); } else { // 选中,添加对应ID return [...prevStatus, chkId]; } }); };
4. 可选:避免重复添加标记
如果addMarkersToMap没有处理重复标记的逻辑,建议先清理现有标记再重新添加,防止地图上出现重复点:
useEffect(() => { // 先清除所有已添加的标记(根据你的地图实现调整) // clearAllMarkers(); const selectedRows = props.rows.filter(row => { const chkId = `${props.window.tablename}_${row.id}_chk`; return checkboxStatus.includes(chkId); }); selectedRows.forEach(row => addMarkersToMap(row)); }, [checkboxStatus, props.rows]);
内容的提问来源于stack exchange,提问作者evan
相关产品推荐
相关产品推荐

