React项目Axios请求Navbar用户信息重复触发12次问题咨询
问题根本原因
- 你把
axios.get请求直接写在了函数组件的顶层作用域,React函数组件每次重渲染都会从头到尾执行一遍组件内的所有顶层代码,所以每次重渲染都会触发一次新的请求 - 请求成功后你调用了
setUsername修改状态,状态更新会触发组件重渲染,重渲染又会发新的请求,就形成了「发请求→改状态→重渲染→发请求」的无限循环,你看到的12次是浏览器或React内部限制了循环次数才没有继续触发 - 如果你的项目开启了React严格模式(
<StrictMode>),开发环境下组件会额外多渲染一次,也会加重请求重复的问题
修复方案
把请求逻辑放到useEffect钩子中,控制仅在依赖项(这里是localToken)变化的时候才触发请求,修改后的逻辑代码如下:
import { useHistory, useEffect } from 'react' // 其余import保持原有逻辑不变 const history = useHistory() // 原useState初始值为数组[''],不符合username的字符串类型,调整初始值 const [username, setUsername] = useState('') const localToken = localStorage.getItem('authToken') // 请求逻辑放入useEffect useEffect(() => { // 无token时直接跳过请求 if (!localToken) return axios.get('https://my-gs-server.herokuapp.com/api/posts/user/info', { headers: { authToken: localToken } }) .then((res) => { if (res.status == 200) { setUsername(res.data.username) console.log(res.data) } else { localStorage.removeItem('authToken') } }) .catch(err => console.log(err)); // 依赖项仅填写localToken,仅token发生变化时才重新发起请求 }, [localToken]) const logout = () => { localStorage.removeItem('authToken') history.push('/login') window.location.reload(); }
额外优化建议
- 导航栏中判断登录状态建议使用组件内的状态判断,不要直接读取localStorage,避免出现状态不同步的问题:可以把localToken也存为组件状态,或者直接用username是否为空判断(前提是无token时不会给username赋值)
- logout操作不需要调用
window.location.reload(),直接修改状态清空username和token就可以实现页面更新,整页刷新会降低用户体验
内容的提问来源于stack exchange,提问作者Thanh Hải
相关产品推荐
相关产品推荐

