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:
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.