调用Spotify刷新token接口时axios请求持续运行,控制台无限打印如何解决
问题产生原因
- 核心原因是
useEffect未传入第二个参数依赖数组,这种情况下useEffect会在每次组件渲染完成后都执行一次:- 每次
useEffect执行都会创建一个新的1秒定时器,定时器触发后调用getData函数 getData中调用SetToken、setExpires更新组件状态,状态更新会触发组件重新渲染- 组件重新渲染后再次执行
useEffect,创建新的定时器,循环往复,定时器数量越来越多,请求和日志打印就会无限触发
- 每次
- 额外注意项:
SetToken是异步状态更新方法,调用后立即打印token拿到的是更新前的旧值,不属于无限打印的核心原因,但属于代码书写的常见误区。
解决方案
- 给
useEffect添加空依赖数组[],保证useEffect仅在组件首次挂载时执行1次,仅创建1个定时器
- 给
- 在
useEffect中返回清理函数,组件卸载时自动清除定时器,避免内存泄漏
- 在
- 可选优化:无需每秒刷新token,可根据接口返回的
expiresIn(单位为秒)设置定时器时长,比如在token过期前1分钟刷新即可,减少不必要的接口请求
- 可选优化:无需每秒刷新token,可根据接口返回的
- 若需要打印最新的token,可直接打印接口返回的
response.data.accessToken,或单独添加useEffect监听token变化后再打印
- 若需要打印最新的token,可直接打印接口返回的
修改后的客户端代码参考:
let getData = () => { axios.request("http://localhost:3001/refresh_token").then((response) => { SetToken(response.data.accessToken); setExpires(response.data.expiresIn); // 直接打印接口返回的最新token即可 console.log(response.data.accessToken); }); }; useEffect(() => { // 仅首次挂载执行,创建1个定时器 const data = setInterval(() => { getData(); }, 1000); // 这里可根据expiresIn调整时长,比如 (expiresIn - 60) * 1000 就是提前1分钟刷新 // 清理定时器 return () => clearInterval(data); }, []); // 空依赖数组 return ( <div className="spotify"> <button onClick={() => { getData(); }} > click </button> </div> );
内容的提问来源于stack exchange,提问作者Barry Allen
相关产品推荐
相关产品推荐

