HKS
HKS

Reputation: 983

How to stay logged in even after page refresh?

I am developing a fullstack app using React & Node.

The following is the home screen.

enter image description here

After a user logs in, the name of the user is displayed in the navbar and the response from the server (including the JWT) is saved in the local storage as shown in the following pictures:

enter image description here

enter image description here

Now, when I refresh the page the user is logged out. This should not happen because I am sending the token on every request header using axios global defaults as shown in the code snippet below:

frontend/src/App.js

import React from "react";
import { Container } from "react-bootstrap";
import Header from "./components/Header";
import Footer from "./components/Footer";
import Products from "./components/Products";
import { Route, Switch } from "react-router-dom";
import SingleProductView from "./components/SingleProductView";
import Cart from "./components/Cart";
import LoginForm from "./components/LoginForm";
import RegisterForm from "./components/RegisterForm";
import Profile from "./components/Profile";
import Shipping from "./components/Shipping";
import PaymentMethod from "./components/PaymentMethod";
import PlaceOrder from "./components/PlaceOrder";
import axios from "axios";

const {token} = localStorage.getItem("loggedInUser");
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;

const App = () => {
  return (
    <>
      <Header />
      <main className="py-3">
        <Container>
          <Switch>
            <Route path="/placeorder" component={PlaceOrder} />
            <Route path="/payment" component={PaymentMethod} />
            <Route path="/shipping" component={Shipping} />
            <Route path="/profile" component={Profile} />
            <Route path="/register" component={RegisterForm} />
            <Route path="/login" component={LoginForm} />
            <Route path="/product/:id" component={SingleProductView} />
            <Route path="/cart/:id?" component={Cart} />
            <Route path="/" component={Products} exact />
          </Switch>
        </Container>
      </main>
      <Footer />
    </>
  );
};

export default App;

What am I doing wrong? I want the user to stay logged in even after page refresh.

Upvotes: 2

Views: 3453

Answers (1)

Ajeet Shah
Ajeet Shah

Reputation: 19813

Axios will lose its custom (provided by you) default headers settings after page is refreshed.

So, you need to set it again after page refresh (i.e. at App Start). You can do it in a component which always gets mounted before other components do:

In most cases, App component would be the perfect place for that:

// App.jsx

useEffect(() => {
  const { token } = localStorage.getItem("loggedInUser");
  if (token) {
    axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
  }
}, [])

Assuming, you are setting the Token for the first time in localStorage after the Authentication is successful. E.g. in Login component.

Another option could be to write a Request Interceptor for Axios and check if this header exists or not; if not, then set it back from localstorage and let the request proceed.


Using Request Interceptor:

axios.interceptors.request.use(
  function (config) {
    if (!config.headers.Authorization) {
      const { token } = localStorage.getItem('loggedInUser')
      if (token) {
        axios.defaults.headers.common['Authorization'] = `Bearer ${token}` // this will be used in next requests
        config.headers.Authorization = `Bearer ${token}` // this is for current request
      }
    }
    return config
  },
  function (error) {
    return Promise.reject(error)
  }
)

Edit: You are passing token to each AsyncThunkAction. So, all you need to do is initialize the redux state properly. So, in the loginSlice:

function getToken() {
  const { token } = localStorage.getItem("loggedInUser");
  if (token) {
    return { token };
  }
  return null;
}

const initialState = {
  status: "idle",
  user: getToken(),
  error: null,
};

Upvotes: 2

Related Questions