React useState loading状态不更新求助:请求数据时loading始终为false
问题分析与解决方案
嘿,作为Hooks新手遇到这个问题太正常啦!我一眼就瞅出问题所在了——你异步函数的执行顺序搞反了。
问题根源
你在useEffect里调用完fetchData()之后,立刻就执行了setIsLoading(false)。但fetchData是异步函数,里面的await axios(...)会暂停函数执行,等待请求返回结果。这时候外面的代码可不会等它,直接就把isLoading设回false了。相当于isLoading刚被设为true,瞬间又被改成false,所以你console里看到的始终是false。
修正后的代码
把setIsLoading(false)放到异步请求完成的逻辑里,而且一定要加上错误处理,避免请求失败时loading一直卡在true状态:
const Pokedex = () => { const [data, setData] = useState({}); const [isLoading, setIsLoading] = useState(false); const pokemonId = 1; useEffect(() => { const fetchData = async () => { try { setIsLoading(true); // 发起请求前开启loading const result = await axios( `https://pokeapi.co/api/v2/pokemon/${pokemonId}` ); setData(result.data); // 请求成功后更新数据 } catch (error) { // 可选:添加错误提示逻辑,比如弹出提示框或者记录日志 console.error('获取宝可梦数据失败:', error); } finally { setIsLoading(false); // 不管成功还是失败,最后都关闭loading } }; fetchData(); }, [pokemonId]); console.log("loading: ", isLoading); // 渲染逻辑示例:根据loading状态切换显示内容 return ( <div className="pokedex"> {isLoading ? ( <div className="loading">加载中...</div> ) : ( <div className="pokemon-info"> <h2>{data.name}</h2> <p>身高: {data.height / 10}m</p> </div> )} </div> ); };
新手友好提示
- 异步函数内部的代码会按顺序等待,但外部代码不会等待异步函数执行完毕,所以结束loading的逻辑必须放在异步函数内部。
- 用
try/catch/finally包裹异步请求是好习惯:try里放正常请求逻辑,catch处理请求失败的情况,finally里放不管成功失败都要执行的逻辑(比如关闭loading)。 - Hooks的状态更新本身是异步的,但这次的问题和状态更新异步无关,主要是异步函数的执行顺序问题哦~
内容的提问来源于stack exchange,提问作者snazzyy
相关产品推荐
相关产品推荐

