Home > Software design >  Context is cleared when I navigate to another page with the browser address bar
Context is cleared when I navigate to another page with the browser address bar

Time:08-14

The user's data is received from the API on the login page and set in the user context, and after redirecting to the AdminPanelApp, our data that is inside the user context is displayed correctly. But when I am on the AdminPanelApp and while my context contains user information, I go to the loginpage through the address bar, all the context user information is deleted.

How can I fix the problem so that the context information is not deleted

Picture of my app:

picture of my app

App.js:

import React, { useState , useEffect } from "react";
import { Routes,  Route } from "react-router-dom";

import Home          from './Components/Home';
import LoginPage     from './Components/LoginPage';
import AdminPanelApp from './Components/Dashboard/AdminPanelApp';

//Context
import UserContext from "./Context/user";


    function App(){
    
        const [ userinfo , setuserinfo ] = useState({
            userid        : ''  ,
            user_name     : ''  ,
            email         : ''  ,
            token         : ''  , 
        });
    
        return(
            <UserContext.Provider value = {
               {
                userinfo : userinfo ,
                setuserinfo
               }
            }>
                <Routes>
                    <Route path="/"            element= { <LoginPage     /> } />
                    <Route path="/Login"       element= { <LoginPage     /> } />
                    <Route path="/admin-panel" element= { <AdminPanelApp /> } />
                </Routes>
    
            </UserContext.Provider>
    
        );
    }
    
    export default App;

LoginPage.js:

import React , { useState , useEffect , useContext } from "react";
import { useNavigate } from "react-router-dom";
import UserContext from '../Context/user';
import '../assets/css/LoginPage.css';
import axios from "axios";

function LoginPage () {

    let navigate = useNavigate();
    const userContext  = useContext(UserContext);
    let { userinfo } = userContext;
    const [ UserNameInput  , setUserNameInput ] = useState('');
    const [ PasswordInput  , setPasswordInput ] = useState('');

    const UserNameInputHandler = (e) => {
        setUserNameInput(e.target.value)
    }

    const PasswordInputHandler = (e) => {
        setPasswordInput(e.target.value)
    }

    let FormHandler = (e)=> {

        e.preventDefault();

        axios.post(
            `http://127.0.0.1:8000/api/login`,
            {
                email    : UserNameInput  ,
                password : PasswordInput
            }
        ).then( response => {
                
                if( response.data.token ) { 
                    
                    userContext.setuserinfo({
                        userid        : response.data.userid      ,
                        user_name     : response.data.user_name   ,
                        email         : response.data.user_email  ,
                        token         : response.data.token       , 
                    })

                    navigate('/admin-panel');
                  

                }
            }
        )
         .catch( err => {
            console.log(err);
        })
    
    }

    return (

         <>
            <main>
        <form className="row g-3 needs-validation" method="post">
                      <div className="col-12">                
                           <div className="input-group has-validation">
                                <span className="input-group-text" id="inputGroupPrepend">@</span>
                                <input type="text" name="username" onChange={ UserNameInputHandler } className="form-control " id="yourUsername" required/>                
                            </div>
                           <div className="col-12">
                                <input type="password" name="password" onChange={ PasswordInputHandler } className="form-control " id="yourPassword" required/>
                           </div>
               <div className="col-12">
                                 <button className="btn btn-primary w-100" onClick={(e) => FormHandler(e) } type="submit">submit</button>
                           </div>
                 </form>
            </main>

        </>
    )

}

export default LoginPage;

AdminPage.js:

import React , { useEffect , useContext } from "react";
import { useNavigate } from "react-router-dom";

import UserContext   from '../../Context/user';
import '../../assets/css/style.css';

import Header  from './Layouts/Header';
import Sidebar from './Layouts/Sidebar';
import Footer  from './Layouts/Footer';

import Dashboard from "./Dashboard";


// import axios from "axios";


function AdminPanelApp () {

    let navigate = useNavigate();
    const userContext  = useContext(UserContext);
    let { userinfo } = userContext;

    if (userinfo.token){
        return (
            <>
                
                <h1>{ user.state.token } </h1>
               
            </>
        )
    }
    else{
        navigate('/Login');
    }
    
}

export default AdminPanelApp;

UserContext.js:

import React from "react";

const UserContext = React.createContext({
    userinfo      : {}          ,
    setUser       : () => {  }  ,
})

export default UserContext;

CodePudding user response:

Navigating with browser's address bar refreshes the page, while navigate does not. And after a page refresh everything come to its initial value. Your context would take that initial object given to that useState in App which is:

{
  userid: "",
  user_name: "",
  email: "",
  token: "",
}

If you don't wanna loose data accros page refreshes (different visites), you should use for example localStorage. For that you can first change FormHandler to:

let FormHandler = (e) => {
  e.preventDefault();

  axios
    .post(`http://127.0.0.1:8000/api/login`, {
      email: UserNameInput,
      password: PasswordInput,
    })
    .then((response) => {
      if (response.data.token) {
        let user = {
          userid: response.data.userid,
          user_name: response.data.user_name,
          email: response.data.user_email,
          token: response.data.token,
        };
        userContext.setuserinfo(user);
        localStorage.setItem("user", JSON.stringify(user));
        navigate("/admin-panel");
      }
    })
    .catch((err) => {
      console.log(err);
    });
};

And change that state definition inside App to this:

const [userinfo, setuserinfo] = useState(
  !localStorage.getItem("user")
    ? {
        userid: "",
        user_name: "",
        email: "",
        token: "",
      }
    : JSON.parse(localStorage.getItem("user"))
);

CodePudding user response:

Data regarding user logins should be handled from the backend using sessions. Example with Express Js backend

But if you need to:

You are already using react router dom, if you wish to move from pages you can use the <Link> Tags which won't refresh your page, but if you update the address bar, it will refresh the page causing you to lose your context data.

And also regarding your question on using local storage, it is not safe to use local storage for any kind of user logins as this data is not encrypted.

  • Related