上下文 api 状态发生变化,但在刷新浏览器之前不会反映

Posted

技术标签:

【中文标题】上下文 api 状态发生变化,但在刷新浏览器之前不会反映【英文标题】:context api state changes but doesn't reflects untill refreshes browser 【发布时间】:2020-11-04 22:54:14 【问题描述】:

我正在更新状态并将令牌存储在本地存储中。 单击登录按钮后,状态会发生变化,但在我刷新浏览器选项卡之前不会进入仪表板页面。 为什么它没有自动检测状态并更新它?

逻辑:如果令牌在本地存储中可用,则应将其重定向到仪表板。否则,应该会出现登录页面,并且在身份验证后应该重定向到仪表板。

下面是用户上下文和登录页面

用户上下文

import React,  createContext, Component  from 'react';
import  Redirect  from 'react-router-dom';

export const UserContext = createContext();
class UserContextProvider extends Component 

    state = 
        isLoading: false,
        isAuthenticated: false,
        token: null,
        UserName: null,
        Email: null,
        Role: null
    

    auth = (auth, profile) => 
        this.setState = (
            isAuthenticated: auth,

        , () =>  );
        if (profile) 
            localStorage.setItem("token", profile.token);
            this.setState = (
                token: profile.token
            , () =>  );
         else 
            this.setState = (
                token: null,
                UserName: null,
                Email: null,
                Role: null
            );
        

    

    isLoading = load => 
        this.setState( isLoading: load )
    

    logout = () => 
        localStorage.removeItem("token")
        this.setState(
            isAuthenticated: false,
            token: null,
            UserName: null,
            Email: null,
            Role: null
        )
    

    componentDidMount = async () => 
        if (localStorage.getItem("token")) 
            const base64Url = localStorage.getItem("token").split('.')[1];
            const base64 = base64Url.replace('-', '+').replace('_', '/');
            var tokenData = (JSON.parse(window.atob(base64)));
            await this.setState(
                isAuthenticated: true,
                token: localStorage.getItem("token"),
                UserName: tokenData.name,
                Email: tokenData.email,
                Role: tokenData.role

            );
        
        return <Redirect to="/login" />

    

    render() 

        return (
            <UserContext.Provider value= ...this.state, auth: this.auth, isLoading: this.isLoading, profileData: this.profileData, logout: this.logout >
                this.props.children
            </UserContext.Provider>
        );
    


export default UserContextProvider;

登录.jsx

const Login = () => 

    const  auth, profileData, token, isAuthenticated  = useContext(UserContext);

    const [email, setemail] = useState('');
    const [password, setpassword] = useState('');
    const [error, setError] = useState(null)

    const handlesubmit = (e) => 
        e.preventDefault();
        const user = 
            Email: email,
            Password: password,
        
        axios.post("http://localhost:2000/user/", user)
            .then(res => 
                if (res.data.error) 
                    setError(res.data.msg);
                    auth(res.data.valid, null);
                 else if (res.data.valid) 
                    setError(null);
                    auth(res.data.valid, res.data)
                
            ).catch(error => 
                console.log(error)
            );
    

    return (
        <div>
            console.log(isAuthenticated, token)
            isAuthenticated ? <Redirect to='/dashboard' /> : <Redirect to='/login' />
            <div className="container mt-5">
                <div className="col-md-6 mx-auto text-center">
                    <div className="header-title">
                        <h1 className="wv-heading--title">
                            Login Here!
                        </h1>
                    </div>
                </div>
                <div className="row mt-5">
                    <div className="col-4 mx-auto">
                        <div className="myform form ">
                            <form onSubmit=handlesubmit>

                                <div className="form-group">
                                    <input type="email" name="email" value=email onChange=(e) =>  setemail(e.target.value)  className="form-control" id="email" placeholder="Email" required />
                                </div>

                                <div className="form-group">
                                    <input type="password" value=password name="password" onChange=(e) =>  setpassword(e.target.value)  id="password" className="form-control" placeholder="Password" required />
                                </div>

                                
                                    error ?
                                        <div className="mt-3 mb-3">

                                            <p style= color: "red", fontSize: "8" > <b>Error :</b> error</p>
                                        </div>
                                        :
                                        null
                                


                                <div className="text-center ">
                                    <button type="submit" className="btn btn-outline-info">Login</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>

    )


export default Login;

【问题讨论】:

res.data.valid 是否返回布尔值? 【参考方案1】:

我明白了。 用户上下文认证函数中的 setState 有错误。

【讨论】:

以上是关于上下文 api 状态发生变化,但在刷新浏览器之前不会反映的主要内容,如果未能解决你的问题,请参考以下文章

React/Nextjs 上下文提供程序状态在第一次加载/刷新时无法访问,但在状态更改时工作正常

状态对象发生变化时更新上下文

Redux 路由器 - 刷新后如何重播状态?

无法打开相机意图。 queryIntentActivities 在 api 级别 30 返回一个空列表,但在级别 29 中找到结果。发生了啥变化?

如果它们的状态在 React useEffect 中发生变化,如何区分上下文值

当提供者组件父状态发生变化时,为啥不能更新子组件中的值(带有反应上下文)?