'Reduxjs/toolkit store loses state when I click on a link served by react-router
I'm building a fullstack web app using React. I have built a number of such apps with the MERN stack but this the first time I am incorporating reduxjs/toolkit and react-router. Major dependencies are: "@reduxjs/toolkit": "^1.8.1", "react": "^18.0.0", "react-redux": "^7.2.8", and "react-router-dom": "^6.3.0".
I am currently working on the login feature. When the user logs in, the app fetches the data from the db and returns it to react, which then stores the user's id and username in the redux store. At that point, the user is logged in and I have access to the user's store across all components. The trouble starts when I click on the navbar or type out the url. At that point, the user's state in the store is lost so the application can no longer remember that the user is logged in.
I have figured out that state is not persisting when one navigates away but since I am new (I did a bootcamp in fullstack development last year), I have not been able to figure out where to look for solutions. While trying to resolve the issue, I have found multiple possible solutions such as using local storage, using redux-persist, but I have no idea what the canonical approach should be. One thing I have tried is to substite in the NavBar component with but that did not work.
Any suggests would be appreciated, even if they're just pointers to where I might find the solution. Would also appreciate help on determining the canonical approach and solution in this case. Thank you so much.
Here are relevant snippets of the code:
(1) the main entry point, index.js:
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
(2) App.jsx:
import React from "react";
import { useSelector } from "react-redux";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Navbar from "./components/Navbar";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Login from "./pages/Login";
import Notify from "./components/Notify";
export default function App() {
const notify = useSelector((state) => state.notification);
return (
<React.Fragment>
{notify.active && <Notify />}
<Navbar />
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/register" element={<Register />} />
<Route path="/login" element={<Login />} />
</Routes>
</BrowserRouter>
</React.Fragment>
);
}
(3) - the UserSlice
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
logged: false,
userId: "",
username: "",
};
export const UserSlice = createSlice({
name: "User",
initialState,
reducers: {
setUser(state, action) {
return (state = {
logged: true,
userId: action.payload.userId,
username: action.payload.username,
});
},
clearUser(state) {
return (state = { logged: false, userId: "", username: "" });
},
},
});
export default UserSlice;
export const { setUser, clearUser } = UserSlice.actions;
(4) - The Store
import { configureStore } from "@reduxjs/toolkit";
import NavBarSlice from "./NavBarSlice";
import NotificationSlice from "./NotificationsSlice";
import SubscribeSlice from "./SubscribeSlice";
import UserSlice from "./UserSlice";
const store = configureStore({
reducer: {
navbar: NavBarSlice.reducer,
notification: NotificationSlice.reducer,
user: UserSlice.reducer,
},
});
export default store;
(5) The NavBar
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
export default function Navbar() {
// access the user state from the store
const user = useSelector((state) => state.user);
return (
<React.Fragment>
<nav className="nav-stle">
<div className="container-top">
<div className="container-internal">
<div className="container-gen">
<a href="/" className="link-gen" > Home </a>
<a href="/register" className="link-gen"> register </a>
<a href="/login" className="{user.logged ? "user-logged-in" : "user-not-logged-in"}">login </a>
</div>
</div>
</div>
</nav>
</React.Fragment>
);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
