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 是如何工作的,但我假设您不想在同一个按钮中调用 logoutupdateLogin(它只会让您登录)。 我正在尝试调用 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 限制嵌套更新的数量以防止无限循环

React hook useEffect 永远/无限循环连续运行

React Hook 注意事项