【问题标题】:Why is my react state not changing properly?为什么我的反应状态没有正确改变?
【发布时间】:2020-08-21 21:55:16
【问题描述】:

我正在尝试在 react 中使用 firebase 进行身份验证。 这是跟踪我的身份验证状态的组件。

    import { useState} from "react";


    function useAuth(fbAuth) {
       const [isAuthenticated, setIsAuthenticated] = useState(false);
       const createEmailUser = (email, password) => fbAuth.createUserWithEmailAndPassword(email, password);
       const signInEmailUser  = (email, password) => fbAuth.signInWithEmailAndPassword(email, password);
       const signOut = fbAuth.signOut();

       fbAuth.onAuthStateChanged(async user=> {
          if (user) {
             await setIsAuthenticated(true);
             console.log(isAuthenticated, "should be true")
             return
          } else {
             await setIsAuthenticated(false);
             console.log(isAuthenticated, "should be false")
             return
          }

        });

       return {isAuthenticated, createEmailUser, signInEmailUser, signOut};

    }

    export default useAuth

单击登录时的控制台日志是

2useAuth.js:13 false "应该是真的"

2useAuth.js:17 false "应该是假的"

2useAuth.js:17 true "应该是 false"

4useAuth.js:17 false "应该是假的"

【问题讨论】:

    标签: javascript reactjs firebase firebase-authentication


    【解决方案1】:

    setIsAuthenticated 函数不返回承诺,所以在这里使用await 并没有真正做任何事情。最重要的是,isAuthenticated 的值永远不会被修改(调用setIsAuthenticated 不会改变你在钩子开始时已经设置的变量的值)。基本上,在您的 onAuthStateChanged 函数中执行 console.log 没有意义,也不会达到您的预期。如果您想更好地了解正在发生的事情,请尝试将console.log 放在函数的开头,然后打印您希望它会改变的事实。所以是这样的:

    import { useState, useEffect } from "react";
    
    function useAuth(fbAuth) {
       const [isAuthenticated, setIsAuthenticated] = useState(false);
       const createEmailUser = (email, password) => fbAuth.createUserWithEmailAndPassword(email, password);
       const signInEmailUser  = (email, password) => fbAuth.signInWithEmailAndPassword(email, password);
       const signOut = fbAuth.signOut();
    
       console.log('isAuthenticated', isAuthenticated)
       //I'm assuming you only need to register the fbAuth.onAuthStateChanged
       //callback once. So We use useEffect with an empty array to have it
       //only run the first time this is rendered.
       useEffect(() => {
           fbAuth.onAuthStateChanged(async user=> {
              if (user) {
                 setIsAuthenticated(true);
                 console.log('isAuthenticated should be true after this')
              } else {
                 setIsAuthenticated(false);
                 console.log('isAuthenticated should be false after this')
              }
            });
        }, [])
    
        return {isAuthenticated, createEmailUser, signInEmailUser, signOut};
    
    }
    
    export default useAuth
    

    你会期待

    //Initial render
    isAuthenticated false
    
    //Click log-in
    isAuthenticated should be true after this
    isAuthenticated true
    
    //Click log-out
    isAuthenticated should be false after this
    isAuthenticated false
    

    【讨论】:

      【解决方案2】:

      我觉得这里没有错。您是在更改之前获取值。要访问最新状态,您可以使用 useEffect 挂钩。 你也没有问过你的问题是什么,你期望什么?

      【讨论】:

      • 我想将 isAuthenticated 用于受保护的路由。如果 isAuthenticated 为真,则应允许用户进入,如果不是,则重新路由回登录页面。核心问题是 isAuthenticated 没有更新,即使单击登录后,我也会重新路由到登录页面。
      • @Rauno 据我了解,拥有一个正在寻找isAuthenticated 的对象怎么样 - 类似于我在 [react-router] reacttraining.com/react-router/web/example/auth-workflow 中找到的 fakeAuth 的另一种方式,我过去使用的是使用 redux 并将其作为道具传递给不同的组件,但我认为这里没有必要
      猜你喜欢
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 2021-02-12
      • 2020-06-23
      • 1970-01-01
      • 2020-04-22
      相关资源
      最近更新 更多