Home > Software design >  How to keep token in Redux state after page reload?
How to keep token in Redux state after page reload?

Time:11-21

so I'm using Redux-Toolkit Query on my project, and I have an authSlice, where I keep the authenticated user info and an access_token.

I also keep this info in local storage so whenever I reload the page I can get the values from the local storage and save them in the state.

The catch is that I have a RequiredAuth component that checks if the user trying to access specific routes is authenticated, by checking if there is an access_token in the state, it works fine except that if I reload this page while I'm authenticated I will be redirected to my login page.

The RequiredAuth component code:

import { useLocation, Navigate, Outlet } from "react-router-dom";
import { useSelector } from "react-redux";
import { selectToken } from "./authSlice";


const RequireAuth = () => {
  const token = useSelector(selectToken)
  const location = useLocation()

  return (
    token ? <Outlet /> : <Navigate to="/auth/login" state={{ from: 
location}} replace />
  )
}

export default RequireAuth

Code that gets user info and token from local storage when the page is reloaded and adds it to state:

import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setCredentials, selectToken } from '../features/auth/authSlice';


const Header = () => {
  const dispatch = useDispatch()
  const [user, setUser] = useState(JSON.parse(localStorage.getItem('profile')))
  const stateToken = useSelector(selectToken)

  useEffect(() => {
    if(user?.access_token && !stateToken) {
      dispatch(setCredentials({ user: user.user, access_token: user.access_token }))
    }
  }, [])

  // Omited code, not relevant



  return (
    <header className='nav-bar'>
      // Omited code, not relevant
    </header>
  )
}

export default Header

I believe whenever I reload a page where a user needs to be authenticated this happens: in the "RequiredAuth" I will get a null access_token from the state, so I get redirected and only then my useEffect will copy the local storage data to the state.

I fixed this problem by changing the RequiredAuth component to this:

import { useLocation, Navigate, Outlet } from "react-router-dom";

const RequireAuth = () => {
  const profile = JSON.parse(localStorage.getItem('profile'))
  const location = useLocation()

  return (
    profile?.access_token ? <Outlet /> : <Navigate to="/auth/login" state={{ from: 
  location}} replace />
  )
}

export default RequireAuth

But I would like to know if there is a better way to keep data in state after reloading a page in order to solve this problem because getting it from local storage feels counterintuitive, since the data will be stored in the state after the useEffect logic completes.

CodePudding user response:

You can't keep data with a refresh. Netherless, you can use this package. This package keeps the data inside the localstorage and populate automatically the store on a refresh.

CodePudding user response:

I think this redux-persist package can help. It basically stores your state inside localStorage/sessionStorage and it will rehidrate your state every time you refresh the page.

  • Related