简体   繁体   English

React Context API 不更新商店

[英]React Context API not updating store

I am working on refresh token.我正在处理刷新令牌。 I faced some problems with context api store.我在上下文 api 存储方面遇到了一些问题。 Store gives me old value.商店给了我旧的价值。 Please look at refreshToken method there is comment explaining error.请查看 refreshToken 方法,那里有解释错误的注释。 I dont't understant why if I console.log(store) React return me old value not new value.我不明白为什么如果我 console.log(store) React 返回旧值而不是新值。

Repeating because Stackoverlow ask me to more describe text重复是因为 Stackoverlow 要求我更多地描述文本

I am working on refresh token.我正在处理刷新令牌。 I faced some problems with context api store.我在上下文 api 存储方面遇到了一些问题。 Store gives me old value.商店给了我旧的价值。 Please look at refreshToken method there is comment explaining error.请查看 refreshToken 方法,那里有解释错误的注释。 I dont't understant why if I console.log(store) React return me old value not new value.我不明白为什么如果我 console.log(store) React 返回旧值而不是新值。

import React, { useState, createContext, useEffect } from 'react';
import {MainUrl, ApiUrl} from '../config';
export const StoreContext = createContext();

export const StoreProvider = props => {
    const getToken = () => localStorage.getItem("token");

const initState = () => ({
    token: getToken(),
    isAuth: false,
    userRole: "",
    userName: "",
    userGroupId: null,
    mainUrl: MainUrl,
    apiUrl: ApiUrl,
})

const [store, setStore] = useState(initState());

const getUserInfo = async () => {
    if (getToken()) {
        try {
            const apiConfig = {
                method: "GET",
                headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${store.token}`,
                },
            };

            const response = await fetch(`${store.apiUrl}get-me`, apiConfig);
            const responseJson = await response.json();

            if (response.ok) {
                // Update Context API
                setStore({
                    ...store,
                    userRole: responseJson.role,
                    userName: responseJson.name,
                    userGroupId: responseJson.group_id,
                    isAuth: true,
                })

            } else if(response.status === 401) {
                await refreshToken();
                // Here I want call this function with refreshed token but React gives old token, although I updated token in refreshToken method
                getUserInfo();
            } else {
                throw new Error(`Возникла ошибка во получения информации об пользователе. Ошибка сервера: ${responseJson.error}`);
            }
        } catch (error) {
            console.log(error);
        }
    }
}

const logout = async (routerHistory) => {
    try {
        const apiConfig = {
            method: "GET",
            headers: {
                "Accept": "application/json",
                "Content-Type": "application/json",
                "Authorization": `Bearer ${store.token}`,
            },
        };

        const response = await fetch(`${store.apiUrl}logout`, apiConfig);
        const responseJson = await response.json();

        if (response.ok) {
            // Remove token from localstorage
            localStorage.removeItem("token");
            // Reset Context API store
            setStore(initState());
            // Redirect to login page
            routerHistory.push("/");
        } else if(response.status === 401) {
            await refreshToken();
            logout(routerHistory);
        } else {
            throw new Error(`Возникла ошибка во время выхода. Ошибка сервера: ${responseJson.error}`);
        }
    } catch (error) {
        console.log(error);
    }
}

const refreshToken = async () => {
    try {
        const apiConfig = {
            method: "GET",
            headers: {
                "Accept": "application/json",
                "Authorization": `Bearer ${store.token}`,
            },
        };

        const response = await fetch(`${store.mainUrl}refresh-token`, apiConfig);
        const responseJson = await response.json();

        if (response.ok) {
            // Update token in local storage
            localStorage.setItem("token", responseJson.token);
             // Update Context API
            setStore({
                ...store,
                userRole: 'some new role',
                token: responseJson.token,
            })
            // Here I expect that userRole and token are changed but if I console.log(store) I get old token and null for userRole
            console.log(store);
        }  else {
            throw new Error(`Возникла ошибка во время обновления токена`);
        }
    } catch (error) {
        throw error;
    }
}

useEffect(() => {
    // Get user info
    getUserInfo();
}, [])

return(
    <StoreContext.Provider value={[store, setStore, logout, getUserInfo]}>
        {props.children}
    </StoreContext.Provider>
);

} }

Your setStore() function from useState() hook is an async function, hence you don't get the updated value from your console.log() call (just after the setStore() ) immediately. useState()钩子中的setStore()函数是一个异步函数,因此您不会立即从console.log()调用(就在setStore()之后console.log()获得更新的值。

Also, there's no facility of providing a callback as the second argument to setStore() function, where you can log the updated state.此外,没有提供回调作为setStore()函数的第二个参数的setStore() ,您可以在其中记录更新的状态。

However, you can move your console.log(store) call inside a useEffect() hook, which triggers after every state update and ensures that you'll get the updated state.但是,您可以将console.log(store)调用移动到useEffect()挂钩内,该挂钩在每次状态更新后触发并确保您将获得更新后的状态。

useEffect(() => {
    console.log(store);
})

So, as far as the title of your question "React Context API not updating store" is concerned, it's actually updating.因此,就您的问题“React Context API 未更新商店”的标题而言,它实际上是在更新。 It's just you are logging it before it is updated.只是您在更新之前记录它。

Hope this helps!希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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