React useState 不更新(立即)

时间:2021-05-16 08:00:36

标签: reactjs authentication

新的反应和钩子,我正在尝试使用钩子做一个登录模块。但是,当我无法更新我的 Auth 状态时。在别处读到 useState 不会立即更新,需要与 useEffect() 结合才能更新。但是我在自定义钩子中使用 useState 并且不确定如何通过 useEffect 或其他方式进行更新。

我在这里做某种反模式吗?有人可以帮忙吗?

const useAuth = () => {
    const [auth, setAuth] = useState( {} );

    useEffect(()=>{
        console.log(auth)
    },[])

    return {auth, setAuth}
}

export const useHandleLogin = (props) => {
    const {auth, setAuth} = useAuth()
    const  history = useHistory();

    useEffect(()=>{
        console.log(auth)
    },[])

    const login = () => { 

        console.log('login action called---- ');

        /* check if user is login */
        if(localStorage.getItem('user')){
            console.log('got user' );
        } else {
            console.log('no user, calling backend to authenticate... ' );
            // change to login api 
            axios.get(`http://localhost:3001/projects`)
            .then(res => {
                console.log('call api' /* + JSON.stringify(res) */);
            })
            localStorage.setItem('user', JSON.stringify({username:'abc',role:'123'}))
            console.log('login done' + JSON.stringify(auth));
            console.log('login done2' + auth.authenticated);
        }

        setAuth({
            authenticated: true,
            displayName: 'My Name',
            email: 'xxx@abc.com',
            role: 'admin'
        })

        console.log("sending to success page" + auth + JSON.stringify(auth)) // Error is here. output is : sending to success page[object Object]{}

import React, {useEffect} from "react";
import { useHandleLogin } from "./LoginUtil"

const TestLoginPage = () => {

  const { auth, login } = useHandleLogin();

  const Clogin = () => {
    
    console.log('auth: ' + auth)
    login();
  };
  
      return (
        <React.Fragment>
          <div>login</div>
          <button onClick={Clogin} > Login </button>
        </React.Fragment>
      );
    }

    export default TestLoginPage;

2 个答案:

答案 0 :(得分:0)

似乎您缺少在 useEffect() 依赖项数组中添加一些依赖项。此外,为了生成像 login() 这样的回调的新实例,您应该将它包装在 useCallback() 中并在数组中添加必要的依赖项。从外观上看,

  • useEffect() 缺少依赖项数组中的 auth
  • login() 应包含在 useCallback() 中,并且必须具有 auth 依赖项 数组
  • Clogin() 必须包含在 useCallback() 中,并且必须有 authlogin 在依赖数组中

您可以使用 add eslint-plugin-react-hooks,它可以帮助您在错过依赖项时提示警告。

答案 1 :(得分:0)

经过几天的尝试和阅读,以下是我认为正确的实现方式。

import React, {  useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { Redirect } from "react-router-dom";
import axios from 'axios';


export const useAuth = (props) => {

/*  const init = localStorage.getItem('user1')? true : false */
    const init = {authen : false}
    const [auth, setAuth] = useState(init);
    const  history = useHistory();

    console.log("auth initial " + auth)

    const checkAuthStatus = () => {
        return !!auth.authen
    }

    const login = () => {
        console.log('login action called---- ');
    
        let success = true 

        if(success){
            setAuth({authen : true})
        }else{ 
            setAuth ({authen : false})
        }
        console.log('push history==========' )
    /*      history.push('/testLoginOK');
        history.go();  */
    }

    const logout = () => {
        console.log('logout action called---- ');
        setAuth ({authen : false})
        history.push('/testLogin');
        history.go(); 
    }



    useEffect(() => {
        console.log("useEffect auth "+auth.authen)
        if(!!auth.authen){
/*             history.push('/testLoginOK');
            history.go();  */
        }

    })

    return {auth, checkAuthStatus, login, logout}
}

/* export default useAuth */