React Context API not updating store

旧街凉风 提交于 2020-01-03 05:33:08

问题


I am working on refresh token. I faced some problems with context api store. Store gives me old value. Please look at refreshToken method there is comment explaining error. I dont't understant why if I console.log(store) React return me old value not new value.

Repeating because Stackoverlow ask me to more describe text

I am working on refresh token. I faced some problems with context api store. Store gives me old value. Please look at refreshToken method there is comment explaining error. I dont't understant why if I console.log(store) React return me old value not new value.

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>
);

}


回答1:


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.

Also, there's no facility of providing a callback as the second argument to setStore() function, where you can log the updated state.

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.

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. It's just you are logging it before it is updated.

Hope this helps!



来源:https://stackoverflow.com/questions/59475866/react-context-api-not-updating-store

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!