react-cookie generating empty cookie when refreshing specific route

101 Views Asked by At

I'm new to the MERN stack and am running into an issue with react-cookie. I am attempting to store a JWT token as a cookie named "acces_token" and use it across other routes. When I login/create and navigate the user to the "/Profile" route the cookie works exactly as expected but if I refresh the "/Profile" route at all, there is an empty "acces_token" cookie generated and its causing me issues. If I navigate away from the profile page the "/Profile" cookie is deleted and my root "/" cookie stays as desired. I originally assumed this is because the "/Profile" routes child routes but even when removing the children, I get the same result. Any useful docs or examples would be appreciated.

Profile.jsx

import Navbar from "../components/Navbar"
import testImg from "../assets/galleryImages/img1.jpg"
import "../stylesheets/profile.scss"
import { useEffect, useState } from "react"
import { useNavigate, Outlet, Link } from "react-router-dom"
import { useCookies } from "react-cookie"
import axios from "axios"
import { useGetUserID } from "../hooks/useGetUserID"

const profile = () => {

    //Use cookies to check if a user is logged in
    const [cookies, setCookies, removeCookies] = useCookies("access_token")
    const [userInfo, setUserInfo] = useState({})

    //useNavigate hook to redirect on logout
    const navigate = useNavigate();

    //Custome hook to get user id from local storage
    const userID = useGetUserID();

    //Logout function clears access token from cookies 
    //and userID from localstorge then redirects to home page
    const logout = () => {
        removeCookies("access_token")
        window.localStorage.removeItem("userID")
        navigate("/Login")
    }

    //Use Effect will load current user info
    //ISSUE: Loads when user logins in and is navigated from login page but will not load when returning to login page.
    useEffect(() => {
            const fetchUser = async () => {
                try {
                    const response = await axios.get(
                        `${import.meta.env.VITE_BASE_URI}/auth/profile/${userID}`,
                        { headers: { auth: cookies.access_token } }
                    );
                        setUserInfo(response.data);
                } catch (err) {
                    console.log(err);
                }
            }
            fetchUser();
    }, [])

  return (
    <div className="banner">
          <Navbar />
          <div className="profileContent container">
              <div className="profileNav">
                  <img src={testImg} alt="Profile Image" />
                  <h3>{userInfo.fname} {userInfo.lname}</h3>
                  <ul>
                      <li><Link className="profileNavLinks" to="UserProfile">Profile</Link></li>
                      <li><Link className="profileNavLinks" to="Appointments">Appointments</Link></li>
                      <li><a className="profileNavLinks" onClick={logout}>Logout</a></li>
                  </ul>
              </div>
              <div className="profileInformation">
                  <Outlet />
              </div>
          </div>
    </div>
  )
}

export default profile

main.jsx

import React from 'react'
import ReactDOM from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from "react-router-dom"
import { CookiesProvider } from 'react-cookie'
import Home from "./pages/home"
import Services from "./pages/services.jsx"
import About from "./pages/about.jsx"
import Gallery from "./pages/gallery.jsx"
import Vehicles from "./pages/vehicles.jsx"
import Login from "./pages/login.jsx"
import Schedule from './pages/schedule.jsx'
import Register from "./pages/register.jsx"
import Profile from "./pages/profile.jsx"
import Appointments from "./pages/appointments.jsx"
import UserProfile from "./pages/userProfile.jsx"
import ErrorPage from "./pages/error-page.jsx"
import "./stylesheets/main.scss"


const router = createBrowserRouter([
  {
    index: true,
    path: "/",
    element: <Home />,
    errorElement: <ErrorPage />,
  },
  {
    path: "/Services",
    element: <Services />,
  },
  {
    path: "/Gallery",
    element: <Gallery />,
  },
  {
    path: "/About",
    element: <About />,
  },
  {
    path: "/Vehicles",
    element: <Vehicles />,
  },
  {
    path: "/Login",
    element: <Login />,
  },
  {
    path: "/Register",
    element: <Register />,
  },
  {
    path: "/Profile",
    element:<Profile />,
    children: [
        {
          path: "UserProfile",
          element:<UserProfile />,
        },
        {
          path: "Appointments",
          element:<Appointments />,
        },
    ]
  },
  {
    path: "/Schedule",
    element: <Schedule />,
  },
  
])

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <CookiesProvider>
      <RouterProvider router={router} />
    </CookiesProvider>
  </React.StrictMode>,
)

login.jsx (This is where the cookie is created and routes to /Profile on successful login as expected)

import Navbar from "../components/Navbar"
import FormInput from "../components/FormInput"
import "../stylesheets/formPageStyles.scss"
import { useState } from "react"
import { useCookies } from "react-cookie"
import { useNavigate } from "react-router-dom"
import axios from "axios"

const Login = () => {

  const [formValues, setFormValues] = useState({
    email: "",
    pwd:"",
  })

  const inputs = [
    {
      name: "email",
      type: "email",
      placeholder: "Email...",
      label: "Email:",
      pattern: /^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/,
      required: true,
      errormessage: "Please enter valid email address...",
      
    },
    {
      name: "pwd",
      type: "password",
      placeholder: "Password...",
      label: "Password:",
      required: true,
      errormessage: "Please enter a password...",
    },
  ]

  //Setting state for form values on each change of the value
  const handleChange = (e) => {
    setFormValues({...formValues, [e.target.name]: e.target.value})
  }

  const [errorMessage, setErrorMessage] = useState("");

  //Used to set cookes when user logs in successfully
  const [_, setCookies] = useCookies(["access_token"])

  //useNavigate hook to navigate user after login
  const navigate = useNavigate()
  
  //Attempting to validate user and login
  const onSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await axios.post(`${import.meta.env.VITE_BASE_URI}/auth/login`, { ...formValues });
      if(!response.data.message){
        setCookies("access_token", response.data.token, {path: '/'});
        window.localStorage.setItem("userID", response.data.userID);
        navigate("/Profile/UserInfo");
      }else{
        setErrorMessage(response.data.message);
      }

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

  //building form with formInput component
  return (
      <div className="banner">
        <Navbar />
        <div className="formPageContent">
          <h1>Login</h1>
              <form onSubmit={onSubmit}>
                <span className="errorMessage">{errorMessage}</span>
              {inputs.map((input, key) => (
                <FormInput
                  {...input}
                  key={key}
                  value={formValues[input.name]}
                  onChange={handleChange} />
              ))}
                <div className="formGroup">
                  <button type="submit" className="submitBtn">Login</button>
                </div>
              </form>
              <p>Don't have an account? <a className="formLinks" href="Register">Create Account</a></p>
              <p>Forgot Username? <a className="formLinks" href="">Recover Username</a></p>
              <p>Forgot Password? <a className="formLinks" href="">Change Password</a></p>
              
        </div>
    </div>
  )
}

export default Login

I have nowhere in my code that Im aware of that should be creating an access_token cookie at "/Profile". Again the "/Profile" cookie does not generate until you are logged in and refresh the profile page or route back to the profile page. enter image description here

0

There are 0 best solutions below