React中useEffect更新useState后无法立即获取新状态的问题
问题:React状态更新后立即打印仍为空数组
我初始化了一个空数组状态:
const [winnerList, setWinnerList] = useState([]);
通过仅执行一次的useEffect发起请求更新状态:
useEffect(()=>{ fetch("/players").then( res => res.json()).then(data => { if(data) { console.log(data); setWinnerList(JSON.parse(data)); console.log(winnerList); window.localStorage.setItem('winner', JSON.stringify(winnerList)); } }) },[])
现在的问题是:console.log(data)能输出预期的JSON数据,但调用setWinnerList后立刻打印winnerList,结果还是空数组,明明已经用获取到的数据更新了状态。
原因分析
React的状态更新是异步批量执行的,调用setWinnerList并不会立刻修改当前作用域里的winnerList变量。你在setWinnerList之后打印的winnerList,还是当前函数闭包中保存的旧值(也就是初始的空数组)。
另外要注意:如果res.json()已经返回的是解析完成的JSON对象,再调用JSON.parse(data)会报错,这时候直接用data即可。
解决方案
方案1:直接使用获取到的最新数据(推荐)
既然已经拿到了data(或者解析后的parsedData),完全可以直接用这个值做打印和存localStorage的操作,不需要等状态更新:
useEffect(()=>{ fetch("/players") .then(res => res.json()) .then(data => { if(data) { console.log(data); // 先确认res.json()返回的是字符串还是对象,对象的话去掉JSON.parse const parsedData = typeof data === 'string' ? JSON.parse(data) : data; setWinnerList(parsedData); // 直接用parsedData做后续操作 console.log(parsedData); window.localStorage.setItem('winner', JSON.stringify(parsedData)); } }) },[])
方案2:监听状态变化执行后续操作
如果必须依赖更新后的winnerList状态来做操作,可以新增一个useEffect监听winnerList的变化:
const [winnerList, setWinnerList] = useState([]); // 初始请求获取数据 useEffect(()=>{ fetch("/players") .then(res => res.json()) .then(data => { if(data) { console.log(data); const parsedData = typeof data === 'string' ? JSON.parse(data) : data; setWinnerList(parsedData); } }) },[]) // 监听winnerList的变化,状态更新后执行操作 useEffect(()=>{ // 过滤初始空数组的情况 if(winnerList.length === 0) return; console.log(winnerList); window.localStorage.setItem('winner', JSON.stringify(winnerList)); },[winnerList]) // 依赖项填winnerList,状态变化时触发
内容的提问来源于stack exchange,提问作者Adi Elron
相关产品推荐
相关产品推荐

