React Hook SetState 导致无限循环
Posted
技术标签:
【中文标题】React Hook SetState 导致无限循环【英文标题】:React Hook SetState Causing Infinite Loop 【发布时间】:2021-02-13 21:58:34 【问题描述】:以下是我的代码,我试图在我的注销按钮内调用 setState,因为此按钮仅在 Auth0 isLoggedIn 为真时呈现。 这似乎导致了无限循环,我的猜测是因为正在调用 Auth0 API 每次。我正在关注本教程:https://www.youtube.com/watch?v=35lXWvCuM8o 唯一的区别是我试图在没有 onClick 函数的情况下调用 setState, 谁能给我解释一下问题和解决方法,提前谢谢!
我知道我可以使用 localStorage 来维护用户登录会话,但我这样做纯粹是为了学习 React Hooks,
import React, useState, useContext, useCallback from 'react';
import useAuth0 from '@auth0/auth0-react';
import ValueContext from './ValueContext'
const LogoutButton = () =>
const [login, setLogin] = useContext(ValueContext);
const logout, isAuthenticated = useAuth0();
const updateLogin = () =>
setLogin(loggedIn:'false');
;
return (
isAuthenticated && (
<>
<button onClick=() => logout()>
Log Out
</button>
<h1>login.loggedIn</h1>
updateLogin()
</>
)
【问题讨论】:
【参考方案1】:您在渲染函数内部调用updateLogin()
,因此您在每次渲染时都设置了loggedIn: true
。不要将函数或控制台日志直接放在返回函数中,如果必须,将它们放在主 LogoutButton
函数体中。但updateLogin()
只能在某些 onPress 内部调用。
【讨论】:
我把我的按钮改成了这样: 但现在我得到了一个无限循环的重新渲染。 我对你在这里想要完成的事情感到困惑。我不知道 Auth0 是如何工作的,但我假设您不想在同一个按钮中调用logout
和 updateLogin
(它只会让您登录)。
我正在尝试调用 auth0 的登录函数,该函数通过 auth0 对用户进行身份验证。在用户进行身份验证的同时,我想通过上下文更新一个全局变量“loggedIn”,这样我就可以为我的其他组件小夜曲,让用户对他们在未登录时无法访问的某些事物具有新的访问权限,即为什么我最初尝试在没有 onClick 的情况下自行调用 updateLogin()
那你为什么要调用 Auth0 的 logout
如果你试图让用户登录到 Auth0?【参考方案2】:
每次渲染组件时,您都会调用 updateLogin()。这将设置状态变量 loggedIn。这将导致组件再次渲染,并且进程不断循环。
【讨论】:
【参考方案3】:唯一的区别是我尝试在没有 onClick 函数的情况下调用 setState
这是一个很大的不同! setState 不应在渲染函数的主体中调用,或者至少有条件地调用它。否则你会得到 setState -> render -> setState -> render ->... 没完没了。
你可以试试这个:
let alreadySet = false;
const LogoutButton = () =>
const [login, setLogin] = useContext(ValueContext);
const logout, isAuthenticated = useAuth0();
const updateLogin = () =>
setLogin(loggedIn:'false');
;
if(!alreadySet)
alreadySet = true;
updateLogin()
return (
isAuthenticated && (
<>
<button onClick=() => logout()>
Log Out
</button>
<h1>login.loggedIn</h1>
</>
)
注意这一点
let alreadySet = false;
....
if(!alreadySet)
alreadySet = true;
updateLogin()
这意味着loginIn只会更新一次。是你想要的吗?如果不是。您可以使用更多详细信息更新您的问题:)
【讨论】:
我添加了您所指的 sn-p,现在出现错误:超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 updateLogin src/components/LogoutButton.js:14 11 | const 注销,isAuthenticated = useAuth0(); 12 |常量更新登录 = () => 13 | /* 登出(); */ > 14 | setLogin(loggedIn:'false'); | ^ src/components/LogoutButton.js:22 19 |让已经设置=假; 20 |如果(!已经设置) 21 |已经设置=真; |更新登录() | 好的,我更改了 sn-p tolet alreadySet = false; if(!alreadySet && isLoggedIn) alreadySet = true;更新登录() 现在应用程序可以正常工作并正确显示登录按钮,但是一旦我单击登录,并且呈现注销按钮,我再次获得 setLogin 的无限循环,所以我需要弄清楚如何防止它重新更新已经设置回false,有什么想法吗? 嗨 Josh,抱歉回复晚了,我们应该移动“让 alreadySet = false;”在 LogoutButton 函数之外【参考方案4】:如果需要在isAuthenticated为真时使用updateLogin,可以添加useEffect hook。
喜欢这个
useEffect(()=> if (isAuthenticated)
setLogin(loggedIn:'false');
,[isAuthenticated, setLogin] );
【讨论】:
以上是关于React Hook SetState 导致无限循环的主要内容,如果未能解决你的问题,请参考以下文章
react Hook踩坑指北—一文解决你所有关于setState的疑惑
为啥 React setState hook 没有立即更新? [复制]
React setState hook 之前的 param 对象给出了不一致的值
在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState。 React 限制嵌套更新的数量以防止无限循环