Ghost
Ghost

Reputation: 123

React Context API not updating store

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

}

Upvotes: 0

Views: 1481

Answers (1)

Akshit Mehra
Akshit Mehra

Reputation: 767

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!

Upvotes: 2

Related Questions