search

Home  >  Q&A  >  body text

useState in ReactJS not working when updating object

I have the following authentication context provider. After the user successfully authenticates, I set some token values

import axios from "axios";
import { createContext, useContext, useState } from "react";
import Constants from "../common/Constants";
import Payload from "../classes/Payload";

const AuthenticationContext = createContext({
    loggedUserToken: {},
    session: {}
});

export const useAuthenticationStatus = () => useContext(AuthenticationContext);

const AuthenticationContextProvider = ({children}) => {

    const [loggedUserToken, setLoggedUserToken]     = useState({});
    const [session, setSession]                     = useState({});


    const authenticateUser = async (loginEndpoint, email, userPassword) => {         

        let result                                  = {};
        let statusCode                              = -1;
        let statusText                              = '';
        let message                                 = '';
        let session                                 = '';
        let postData                                = {username: email, password: userPassword};

        await axios.post(loginEndpoint, postData, {headers: headerData})
                .then( data => {

                    statusCode                      = data.data.code;
                    statusText                      = data.data.statusText;
                    session                         = data.data.session;
                    message                         = data.data.message;

                    if (statusCode === 200) {                

                        let challengeName           = message.challengeName;
                        let payloadData             = '';
                        
                        if (session !== null && message.challenge !== null) {

                            let userEmail           = message.userEmail;
                            setSession({'sD': session, 'sE': userEmail });
                            
                            if (challengeName === Constants.COGNITO_CHALLENGE_NEW_PASSWORD_REQUIRED ) {
                                statusText          = Constants.AUTHENTICATION_SET_NEW_PASSWSORD;
                                payloadData         = challengeName;
                            }

                            result = { 's': true, 'sT': statusText, 'p': payloadData};

                        } else {
                            statusText              = Constants.AUTHENTICATION_LOGIN_SUCCESSFUL;
                            payloadData             = message;

                            let userpayloadData      = new Payload(payloadData);

                            //set use state for user token - ERROR IN HERE
                            //loggedUserToken IS NOT SET HERE
                            setLoggedUserToken(loggedUserToken => userpayloadData);

                            result = { 's': true, 'sT': statusText, 'p': payloadData};

                        }                        

                    }

                }).catch( error => {
                    
                    result = { 's': false, 'sT': Constants.COMMON_ERROR_MESSAGE, 'p': ''};

                });

        return result;  
    }

    

    return (
        <AuthenticationContext.Provider
            value={{loggedUserToken, authenticateUser, session, setPermanentPassword}}>
            {children}
        </AuthenticationContext.Provider>
    )
};

export default AuthenticationContextProvider;

I used the "loggedUserToken" value in the home view to check if it is available.

import { useEffect } from "react";
import { useAuthenticationStatus } from "../../services/AuthenticateContextProvider";

function HomeView() {

    const {loggedUserToken} = useAuthenticationStatus();
    
    //empty object output
    console.log(loggedUserToken);

    useEffect( () => {
        //empty object output
        console.log(loggedUserToken);
    })

    return (

        
        <div className="col-12">
            
            <div className="row mt-2">
                <div className="col-12">

                </div>
            </div>

            <div className="row mt-5 incident-list-map">

                <div className="col-md-4">

                    <h2>List</h2>
                    
                    <div></div>

                </div>

                <div className="col-md-8">
                    <div id="map" className="map">
                        
                    </div>

                </div>

            </div>

        </div>

    );
}

export default HomeView;

"loggedUserToken" is always empty even if you set it in the authentication provider (even if you print it to the console immediately after "setLoggedUserToken" on the authentication provider). "setSession" is set correctly, the value is read in another view.

I'm not sure what's wrong here

Update: Here is how I use the authentication provider. "Outlet" replaces different views in MainLayout.

import { Outlet } from "react-router-dom";
import MainHeader from "../common/MainHeader";
import MainFooter from "../common/MainFooter";
import AuthenticationContextProvider from "../../services/AuthenticateContextProvider";

function MainLayout() {

    return(

        <div className="main-layout">
            <AuthenticationContextProvider>
                <header>
                    <nav className="navbar navbar-expand-md fixed-top header-area">
                        <MainHeader></MainHeader>
                    </nav>
                </header>
                
                <main className="flex-shrink-0 main-area">
                    <div className="container-fluid">
                        <div className="main-content">
                            
                                <Outlet />
                            
                        </div>
                        
                    </div>
                </main>

                <footer className="footer mt-auto py-3 footer-content">
                    <div className="container-fluid">
                        <MainFooter></MainFooter>
                    </div>
                </footer>
            </AuthenticationContextProvider>
        </div>

    );

}

export default MainLayout;

P粉986028039P粉986028039436 days ago659

reply all(1)I'll reply

  • P粉283559033

    P粉2835590332023-09-22 11:31:13

    I've found a solution. The above error is caused by the layout I'm using. I'm using one layout in authentication views (like login, registration, etc.) and another layout in other views (home, contact us, etc.).

    I have encapsulated them separately into authentication context providers. As follows:

    import { Outlet } from "react-router-dom";
    import MainHeader from "../common/MainHeader";
    import MainFooter from "../common/MainFooter";
    import AuthenticationContextProvider from "../../services/AuthenticateContextProvider";
    
    function MainLayout() {
    
        return(
    
            <div className="main-layout">
                <AuthenticationContextProvider>
                    <header>
                        <nav className="navbar navbar-expand-md fixed-top header-area">
                            <MainHeader></MainHeader>
                        </nav>
                    </header>
                    
                    <main className="flex-shrink-0 main-area">
                        <div className="container-fluid">
                            <div className="main-content">
                                
                                    <Outlet />
                                
                            </div>
                            
                        </div>
                    </main>
    
                    <footer className="footer mt-auto py-3 footer-content">
                        <div className="container-fluid">
                            <MainFooter></MainFooter>
                        </div>
                    </footer>
                </AuthenticationContextProvider>
            </div>
    
        );
    
    }
    
    export default MainLayout;

    import { Outlet } from "react-router-dom";
    import MainHeader from "../common/MainHeader";
    import MainFooter from "../common/MainFooter";
    import AuthenticationContextProvider from "../../services/AuthenticateContextProvider";
    
    function MainLayout() {
    
    
        return(
    
            <div className="main-layout">
                
                    <header>
                        <nav className="navbar navbar-expand-md fixed-top header-area">
                            <MainHeader></MainHeader>
                        </nav>
                    </header>
                    
                    <main className="flex-shrink-0 main-area">
                        <div className="container-fluid">
                            <div className="main-content">
                                
                                    <Outlet />
                                
                            </div>
                            
                        </div>
                    </main>
    
                    <footer className="footer mt-auto py-3 footer-content">
                        <div className="container-fluid">
                            <MainFooter></MainFooter>
                        </div>
                    </footer>
    
            </div>
    
        );
    
    }
    
    export default MainLayout;

    But when I moved the authentication context provider into App.js, it worked. From what I understand, I think what is happening is that the authentication context provider is reset when it moves from the auth layout to the main layout (in the main layout it is a separate context provider). But since I moved the context provider to the top level (App.js), it is now common across all layouts.

    import 'bootstrap/dist/css/bootstrap.css';
    import 'bootstrap/dist/js/bootstrap.js';
    import './App.css';
    import { Route, Routes } from 'react-router-dom';
    import AuthenticationLayout from './components/layouts/AuthenticationLayout';
    import LoginView from './components/authentication/LoginView';
    import ForgotPasswordView from './components/authentication/ForgotPasswordView';
    import MainLayout from './components/layouts/MainLayout';
    import HomeView from './components/main/HomeView';
    import ConfirmEmailView from './components/authentication/ConfirmEmailView';
    import SetNewPassword from './components/authentication/SetNewPassword';
    import AuthenticationContextProvider from './services/AuthenticateContextProvider';
    
    function App() {
    
      return (
    
        <>
          <AuthenticationContextProvider>
            <Routes>
              <Route element={ <AuthenticationLayout /> }>
                <Route path='/' element={ <LoginView /> }></Route>
                <Route path='/login' element={ <LoginView /> }></Route>
                <Route path='/forgotpassword' element={ <ForgotPasswordView />}></Route>
                <Route path='/confirmemail'element={ <ConfirmEmailView /> }></Route>
                <Route path='/setnewpassword' element={ <SetNewPassword /> }></Route>
              </Route>
    
              <Route element={ <MainLayout /> }>
                <Route path='/home' element={ <HomeView /> }></Route>
              </Route>
    
            </Routes>
          </AuthenticationContextProvider>
        </>
    
      );
    
    }
    
    export default App;

    reply
    0
  • Cancelreply