使用多个if语句时React State无法正确更新问题排查
React状态更新异常排查:roots数组无法正确同步
你提供的组件代码里,六个字符串的布尔状态能正常切换,但roots数组总是更新异常,核心问题在于React的状态更新是异步的:
当你在firstStringHandler里调用setFirstString(!firstString)后,React并不会立刻更新firstString的状态值,紧接着调用updateRoots时,读取的还是更新前的firstString旧值,导致selectedRoots的判断逻辑基于旧状态,自然无法生成正确的数组。
两种解决方案:
方案1:用useEffect监听布尔状态变化,自动同步roots
给六个布尔状态加监听,只要其中任何一个变化,就重新计算roots数组:
import { useState, useEffect } from 'react'; const IMETrainer = (props) => { // ROOT STATES const [firstString, setFirstString] = useState(true); const [secondString, setSecondString] = useState(true); const [thirdString, setThirdString] = useState(true); const [fourthString, setFourthString] = useState(true); const [fifthString, setFifthString] = useState(true); const [sixthString, setSixthString] = useState(true); // SELECTED OPTIONS const [roots, setRoots] = useState([1,2,3,4,5,6]); // 用useEffect监听所有布尔状态,自动更新roots useEffect(() => { const selectedRoots = []; if (firstString) selectedRoots.push(1); if (secondString) selectedRoots.push(2); if (thirdString) selectedRoots.push(3); if (fourthString) selectedRoots.push(4); if (fifthString) selectedRoots.push(5); if (sixthString) selectedRoots.push(6); setRoots(selectedRoots); }, [firstString, secondString, thirdString, fourthString, fifthString, sixthString]); // ROOT HANDLERS const firstStringHandler = () => setFirstString(!firstString); const secondStringHandler = () => setSecondString(!secondString); const thirdStringHandler = () => setThirdString(!thirdString); const fourthStringHandler = () => setFourthString(!fourthString); const fifthStringHandler = () => setFifthString(!fifthString); const sixthStringHandler = () => setSixthString(!sixthString); }
方案2:合并状态,直接操作roots数组(更简洁高效)
没必要维护六个独立的布尔状态,直接通过roots数组来判断字符串是否被选中,handler里直接修改数组:
import { useState } from 'react'; const IMETrainer = (props) => { // 直接用roots数组维护选中状态,初始全选 const [roots, setRoots] = useState([1,2,3,4,5,6]); // 通用handler,接收字符串序号 const stringHandler = (num) => { setRoots(prevRoots => { // 判断当前序号是否在数组中,存在则移除,不存在则添加 if (prevRoots.includes(num)) { return prevRoots.filter(item => item !== num); } else { return [...prevRoots, num].sort(); // 排序保持顺序一致 } }); } }
这样调用handler时只需要传对应序号(比如stringHandler(1)),代码量骤减,还彻底避免了异步状态更新的问题。
内容的提问来源于stack exchange,提问作者RyanAcevedo
相关产品推荐
相关产品推荐

