简体   繁体   中英

Why is my react state not changing properly?

I'm trying to authenticate using firebase in react. This is the component that tracks my authentification state.

    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

The console logs when I click log in are

2useAuth.js:13 false "should be true"

2useAuth.js:17 false "should be false"

2useAuth.js:17 true "should be false"

4useAuth.js:17 false "should be false"

The setIsAuthenticated function does not return a promise, so using await here doesn't really do anything. On top of that, the value of isAuthenticated is never modified (calling setIsAuthenticated doesn't change the value of the variable you already set at the beginning of the hook). Basically, doing a console.log within your onAuthStateChanged function doesn't make sense and won't do what you expect. If you want to get a better feel for what is happening, try putting a console.log at the beginning of the function, and just print the fact that you expect it to change. So something like this:

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

You would then expect

//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

I see nothing wrong here. You are the getting the value before it is changed. To access the newest state you can use the useEffect hook. Also you have not asked anything like what is your issue and what do u expect?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM