React useState在useEffect定时器中无法存储更新后值的问题咨询
问题根因
- 闭包陷阱:你的
useEffect依赖数组为空,执行时只会捕获首次渲染的joke初始值[],定时器回调、请求回调里访问的joke永远是这个初始值,不会拿到更新后的状态。 setJoke是异步更新操作:调用后React不会立即修改当前作用域的joke变量,紧接着同步打印必然拿不到最新值。- 定时器清除逻辑位置错误:你写的
if (joke.length !== 0)判断只会在useEffect首次执行时运行一次,后续定时器触发时不会执行这段判断,永远无法触发定时器清除。
修复方案
const [joke, setJoke] = React.useState([]); // 单独监听joke变化,更新后执行业务逻辑、清除定时器 React.useEffect(() => { if (joke.length !== 0) { console.log("JOKE更新后的值: ", joke); console.log("返回True"); // 这里写joke更新后的业务逻辑 } }, [joke]); // 定时器逻辑 React.useEffect(() => { const interval = setInterval(() => { axios.get("https://api.chucknorris.io/jokes/random").then((res) => { setJoke(res.data.value); // 如果要在请求完成后立刻拿到返回值,直接读res即可,不需要读state // console.log("接口返回的joke内容: ", res.data.value); }); console.log("每5秒触发一次"); }, 5000); return () => clearInterval(interval); }, []);
如果只需要请求成功一次就停掉定时器,也可以在请求回调里判断后直接清:
React.useEffect(() => { const interval = setInterval(() => { axios.get("https://api.chucknorris.io/jokes/random").then((res) => { const newJoke = res.data.value; setJoke(newJoke); console.log("请求到的joke: ", newJoke); if (newJoke.length) { clearInterval(interval); console.log("返回True"); } }); }, 5000); return () => clearInterval(interval); }, []);
内容的提问来源于stack exchange,提问作者May
相关产品推荐
相关产品推荐

