user11657014
user11657014

Reputation: 71

lost auth state when page refresh in reactjs hooks

When i login with valid credentials server send JWT to browser i store this JWT in localstore page redirect to home page everything works fine and in home page i have loadUser function which send request to server to get the user details of valid user but when i refresh the page it home page never execute because auth state returns to false and page redirect from home to login page This is App.js

 import React, { Fragment } from "react";
        import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
         import Navbar from "./components/layout/Navbar";
       import Home from "./components/pages/Home";
        import Login from "./components/auth/Login";
        import PrivateRoute from "./components/routing/PrivateRoute";
      import "./App.css";
       const App = () => {
      return (
            <AuthState>
              <Router>
            <Fragment>
              <Navbar />
              <div className="container">
                <Alerts />
                <Switch>
                  <PrivateRoute exact path="/" component={Home} />
                  <Route exact path="/login" component={Login} />
                </Switch>
              </div>
            </Fragment>
          </Router>
         </AuthState>
  );
};
export default App;
This is my authsate code from where my state changes after successful login

import React, { useReducer } from "react";
    import axios from "axios";
    import AuthContext from "./authContext";
    import authReducer from "./authReducer";
    import {
      USER_LOADED,
      AUTH_ERROR,
      LOGIN_SUCCESS,
      LOGIN_FAIL,
      } from "../types";
    const AuthState = props => {
      const initialState = {
          isAuthenticated: null,
          user: null,
      };
      const [state, dispatch] = useReducer(authReducer, initialState);
      // Load User
      const loadUser = async () => {
        if (localStorage.token) {
          setAuthToken(localStorage.token);
        }
        try {
          const res = await axios.get("/api/auth");
          dispatch({ type: USER_LOADED, payload: res.data });
        } catch (err) {
          dispatch({ type: AUTH_ERROR });
        }
      };
      // Login User
      const login = async formData => {
        const config = {
          headers: {
            "Content-Type": "application/json"
          }
        };
        try {
          const res = await axios.post("api/auth", formData, config);
          dispatch({
            type: LOGIN_SUCCESS,
            payload: res.data
          });
          loadUser();
        } catch (err) {
          dispatch({
            type: LOGIN_FAIL,
            payload: err.response.data.msg
          });
        }
      };
      return (
        <AuthContext.Provider
          value={{
                  isAuthenticated: state.isAuthenticated,
              user: state.user,
              loadUser,
            login,
         }}
        >
          {props.children}
        </AuthContext.Provider>
      );
    };
    export default AuthState;

This is reducer code authReducer.js

import {
  USER_LOADED,
  AUTH_ERROR,
  LOGIN_SUCCESS,
  LOGIN_FAIL,
    } from "../types";
   export default (state, action) => {
  switch (action.type) {
    case USER_LOADED:
      return {
        ...state,
        isAuthenticated: true,

        user: action.payload
      };
       case LOGIN_SUCCESS:
      localStorage.setItem("token", action.payload.token);
      return {
        ...state,
          isAuthenticated: true
         };
       case AUTH_ERROR:
    case LOGIN_FAIL:
         localStorage.removeItem("token");
      return {
        ...state,

        isAuthenticated: false,
           user: null,
         };
         default:
      return state;
  }
};

This is private route
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import AuthContext from "../../context/auth/authContext";

const PrivateRoute = ({ component: Component, ...rest }) => {
  const authContext = useContext(AuthContext);
  const { isAuthenticated, loading } = authContext;
  return (
    <Route
      {...rest}
      render={props =>
        !isAuthenticated && !loading ? (
          <Redirect to="/login" />
        ) : (
          <Component {...props} />
        )
      }
    />
  );
};

export default PrivateRoute;

Upvotes: 1

Views: 4641

Answers (2)

Claudio Cortese
Claudio Cortese

Reputation: 1380

That's to be expected.

If you want to persist the token you should save it in localStorage or a cookie.

Then, you should check for the token existence and validity in componentDidMount or in an useEffect (with a void dependency array) if you are using hooks.

It'd be nice if you could show us where you are making AJAX requests because if, for example, you are using Axios you can encapsulate this logic in a request interceptor.

Upvotes: 1

Karthick Ramachandran
Karthick Ramachandran

Reputation: 651

Probably the JSON web token which is used for user authentication/authorization. Can you give us more information about this?

Upvotes: 1

Related Questions