为什么React useState Hook会引发过多重渲染?无限循环报错如何解决
报错根因
你将setUserName这个状态更新方法直接写在了组件的顶层执行逻辑中,每次组件渲染都会无条件执行这段逻辑,触发了无限重渲染循环:
- 组件首次渲染,useEffect中发起接口请求
- 接口请求完成后调用
setCurrentUser更新状态,触发组件第二次渲染 - 第二次渲染时
currentUser.data有值,执行setUserName更新username状态,触发组件第三次渲染 - 第三次渲染时
currentUser.data仍然有值,再次执行setUserName,继续触发重渲染,循环往复超出React的渲染次数限制,触发报错
解决方法
有三种可行的修复方案,按需选择即可:
方案1:将username赋值逻辑移入useEffect
直接在接口请求拿到用户数据后同步更新username,避免在顶层渲染逻辑中更新状态,修正后代码如下:
const [setList, setSetList] = useState({ data: null }); const [currentUser, setCurrentUser] = useState({ data: null }); const [username, setUserName] = useState(); const Token = localStorage.getItem('token') console.log(Token) useEffect(() => { const fetchData = async () => { const setlist = await axios.get( 'http://127.0.0.1:8000/api/set/list/', { headers: { Authorization: `Token ${Token}` } }); const setuserdata = await axios.get( 'http://127.0.0.1:8000/api/user/current/', { headers: { Authorization: `Token ${Token}` } }); setCurrentUser({ data: setuserdata.data }); // 直接在这里更新username即可 setUserName(setuserdata.data.username); setSetList({ data: setlist.data }); }; fetchData(); }, [Token]); console.log('render'); // 删掉原来的顶层setUserName逻辑
方案2:给顶层更新逻辑加判断条件
如果确实需要在顶层处理赋值,增加判断避免重复更新:
// 只有username和当前取到的用户用户名不一致时才触发更新 if (currentUser.data && username !== currentUser.data.username) { console.log("userdata", currentUser.data); console.log("userdata", currentUser.data.username); setUserName(currentUser.data.username); }
方案3:移除冗余的username状态
你的username完全可以从currentUser状态派生出来,不需要单独维护一个独立状态,直接在需要用到用户名的地方使用currentUser.data?.username即可,从根源避免这个问题。
内容的提问来源于stack exchange,提问作者Sungeun Choi
相关产品推荐
相关产品推荐

