组件上的 setState 导致无限循环
A setState on a component causes an infinite loop
我的 App.js
导致无限循环:
function App() {
const [sessionUuid, setSessionUuid] = useState('')
return (
<div className="App">
<Header setSessionUuid={setSessionUuid}/>
<Routes>
<Route path='/about' element={<About />} />
<Route path="/" element={<Home />} />
<Route path="/wine" element={<Wine sessionUuid={sessionUuid} />} />
</Routes>
<Footer />
</div>
);
}
Header
组件显示 login
或 logout
按钮,具体取决于用户是否已登录。只有当用户登录或注销时,组件才会触发 setSessionUuid
函数。
useEffect(() => {
if (user !== '')
setSessionUuid(user.sessionUuid)
else
setSessionUuid('')
}, [user, setSessionUuid])
这会导致 App
组件无限渲染。
我在 Whosebug 上找到了这个解决方法,将 setSessionUuid 函数包装在 wrapperSetParentState = useCallback
函数中,然后将 wrapperSetParentState
传递给登录组件。但是并没有解决问题,无限渲染依旧
const wrapperSetParentState = useCallback(val => {
setSessionUuid(val);
}, [setSessionUuid]);
我想要实现的是,只有路由 wine
上的组件会根据 sessionUuid
的值进行不同的渲染
setSeesionUuid
导致 useEffect 永远循环。
您可以将其从依赖项数组中删除。
useEffect(() => {
if (user !== '')
setSessionUuid(user.sessionUuid)
else
setSessionUuid('')
}, [user])
如果 eslint 给您警告,请添加 //eslint-disable-next-line
。
- setSessionUuid 不应更改并再次导致效果 运行 但根据我最近项目的经验,可以从 useEffect Deps 数组中省略 setState 函数。依赖项中需要用户,因为它可能会更改并成为不同的值。
一直是一场噩梦,但我解决了它,我想与所有相关人员分享错误所在。
首先,我创建了一个沙箱,您可以在 https://codesandbox.io/s/bitter-water-jsblw?file=/src/App.js:367-374
访问它:如您所见,它 运行 很有魅力 ;-) 不需要奇怪的东西,useEffects或其他不必要的东西。
所以,错误不可能存在。
然后,我删除了 my App.js
中唯一的东西,而不是沙盒中的东西。我没有在最初的消息中插入它,因为......它已经在那里几个月没有问题而且对我来说是完全看不见的:任何看不见的东西都会造成问题吗?是的,它可以!
指令是
const langs = navigator.languages; //["en-US", "zh-CN", "ja-JP"]
const userLanguageCode = langs[0].length > 2 ? langs[0].substring(0, 2) : langs;
i18n.changeLanguage(userLanguageCode);
而且,准确地说,是 i18n.changeLanguage(userLanguageCode);
造成了问题。我删除了它,所有内容 运行 都完美无缺,就像在沙盒中一样。
感谢大家的支持,希望这次的不幸经历能给大家带来思考。
再次感谢您
我的 App.js
导致无限循环:
function App() {
const [sessionUuid, setSessionUuid] = useState('')
return (
<div className="App">
<Header setSessionUuid={setSessionUuid}/>
<Routes>
<Route path='/about' element={<About />} />
<Route path="/" element={<Home />} />
<Route path="/wine" element={<Wine sessionUuid={sessionUuid} />} />
</Routes>
<Footer />
</div>
);
}
Header
组件显示 login
或 logout
按钮,具体取决于用户是否已登录。只有当用户登录或注销时,组件才会触发 setSessionUuid
函数。
useEffect(() => {
if (user !== '')
setSessionUuid(user.sessionUuid)
else
setSessionUuid('')
}, [user, setSessionUuid])
这会导致 App
组件无限渲染。
我在 Whosebug 上找到了这个解决方法,将 setSessionUuid 函数包装在 wrapperSetParentState = useCallback
函数中,然后将 wrapperSetParentState
传递给登录组件。但是并没有解决问题,无限渲染依旧
const wrapperSetParentState = useCallback(val => {
setSessionUuid(val);
}, [setSessionUuid]);
我想要实现的是,只有路由 wine
上的组件会根据 sessionUuid
setSeesionUuid
导致 useEffect 永远循环。
您可以将其从依赖项数组中删除。
useEffect(() => {
if (user !== '')
setSessionUuid(user.sessionUuid)
else
setSessionUuid('')
}, [user])
如果 eslint 给您警告,请添加 //eslint-disable-next-line
。
- setSessionUuid 不应更改并再次导致效果 运行 但根据我最近项目的经验,可以从 useEffect Deps 数组中省略 setState 函数。依赖项中需要用户,因为它可能会更改并成为不同的值。
一直是一场噩梦,但我解决了它,我想与所有相关人员分享错误所在。
首先,我创建了一个沙箱,您可以在 https://codesandbox.io/s/bitter-water-jsblw?file=/src/App.js:367-374
访问它:如您所见,它 运行 很有魅力 ;-) 不需要奇怪的东西,useEffects或其他不必要的东西。
所以,错误不可能存在。
然后,我删除了 my App.js
中唯一的东西,而不是沙盒中的东西。我没有在最初的消息中插入它,因为......它已经在那里几个月没有问题而且对我来说是完全看不见的:任何看不见的东西都会造成问题吗?是的,它可以!
指令是
const langs = navigator.languages; //["en-US", "zh-CN", "ja-JP"]
const userLanguageCode = langs[0].length > 2 ? langs[0].substring(0, 2) : langs;
i18n.changeLanguage(userLanguageCode);
而且,准确地说,是 i18n.changeLanguage(userLanguageCode);
造成了问题。我删除了它,所有内容 运行 都完美无缺,就像在沙盒中一样。
感谢大家的支持,希望这次的不幸经历能给大家带来思考。
再次感谢您