CalgaryFlames
CalgaryFlames

Reputation: 706

Resetting the redux store when routing other components in React

Using react-router-dom, react-redux, I tried to implement a website. The website has displayed the content based on the language setting using the redux store. When clicking the language area in Navbar, it callback changeLanguage function, then it changes the state of language in the store and the website displays contents with changed language properly. However, when I click the other link '/home' or '/main' in the navbar, it is landing on the page with resetting the redux store. Could let me know how to deal with this issue?

languageSlice

import { createSlice } from "@reduxjs/toolkit";

export const languageSlice = createSlice({
  name: "language",
  initialState: {
    language: "Fr",
  },
  reducers: {
    getLanguage: (state, action) => {
      return state;
    },
    changeLanguage: (state, action) => {
      if (action.payload == "En") {
        return {
          ...state,
          language: "Fr",
        };
      } else {
        return {
          ...state,
          language: "En",
        };
      }
    },
  },
});

export const { getLanguage, changeLanguage } = languageSlice.actions;
export default languageSlice.reducer;

store.js

import { configureStore } from "@reduxjs/toolkit";
import languageSlice from "./languageSlice";

export default configureStore({
  reducer: {
    languageSlice: languageSlice,
  },
});

LanguageService.js

import { getLanguage, changeLanguage } from "../app/languageSlice";

export const changeLan = (dispatch, language) => {
  dispatch(changeLanguage(language));
};

export const getLan = (dispatch) => {
  dispatch(getLanguage());
};

Index.jsx

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import store from "./app/store";
import { Provider } from "react-redux";
import "bootstrap/dist/css/bootstrap.min.css";

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

reportWebVitals();

App.jsx

import "./App.css";
import React, { useEffect } from "react";
import { MainPage } from "./MainPage";
import { Home } from "./Home";
import { Switch, BrowserRouter, Redirect, Route } from "react-router-dom";
import Navbar from "./layout/NavBar";
import Event from "./staticPages/Event";
import { getLan } from "./service/LanguageService";
import { useDispatch, useSelector } from "react-redux";

function App() {
  const dispatch = useDispatch();
  const language = useSelector((state) => state.languageSlice.language);

  useEffect(() => {
    getLan(dispatch);
    console.log(language);
  }, [language]);

  return (
    <div
      className=" ml-auto mr-auto"
      style={{
        width: "80%",
      }}
    >
      <BrowserRouter>
        <Navbar />
        <Switch>
          <Route exact path="/home" render={() => <Home />} />
          <Route exact path="/main" render={() => <MainPage />} />
          <Route exact path="/event" render={() => <Event />} />         
          <Route component={() => <h3>Page is not found!</h3>} />
        </Switch>
        <Footer />
      </BrowserRouter>
    </div>
  );
}

export default App;

NavBar

import { Nav, Navbar, NavDropdown, Image } from "react-bootstrap";
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeLan, getLan } from "../service/LanguageService";

const NavBar = () => {
  const dispatch = useDispatch();
  const language = useSelector((state) => state.languageSlice.language);

  const changeLanguage = () => {
    changeLan(dispatch, language);
  };


  return (
    <>
      <Navbar collapseOnSelect expand="sm">
        <Navbar.Brand href="/home">
         Home
        </Navbar.Brand>
        <Nav onSelect={changeLanguage}>
          <Nav.Item>
            <Nav.Link href="#">{language}</Nav.Link>
          </Nav.Item>
        </Nav>
        <Navbar.Toggle aria-controls="responsive-navbar-nav" />        
          <Navbar.Collapse id="responsive-navbar-nav">
            <Nav className="ml-auto" light="true">             
              <NavDropdown title="Events" id="nav-dropdown1">
                <NavDropdown.Item href="/event">Latest Events</NavDropdown.Item>
              </NavDropdown>   
              <Nav.Item>
                <Nav.Link href="/main">Access Survey Portal</Nav.Link>
              </Nav.Item>           
            </Nav>
          </Navbar.Collapse>
      </Navbar>
    </>
  );
};

export default NavBar;

EventPage

import React from "react";
import { useSelector } from "react-redux";

const Event = () => {
  const language = useSelector((state) => state.languageSlice.language);

  return (
    <>
      {language != "En" ? (
        <div className="area">
          <section
            className="product_landing_welcome_area product_landing jarallax my-auto"
            id="home"
            style={{ backgroundColor: "#008fac" }}
          >
            <div className="container h-100">
              <div className="row align-items-center">
                <div className="col-sm col-md-12 col-lg-12 text-center">
                  <div
                    className="welcome_text_area m-top-3"
                    style={{
                      width: "100%",
                      paddingBottom: "35px",
                      paddingTop: "35px",
                      marginBottom: "0px",
                    }}
                  >
                    <h3 className="fonts-shadow-into-light text-white">
                      <b>Latest Events</b>
                    </h3>
                  </div>
                </div>
              </div>
            </div>
          </section>
        </div>
      ) : (
        <div className="area">
          <section
            className="product_landing_welcome_area product_landing jarallax my-auto"
            id="home"
            style={{ backgroundColor: "#008fac" }}
          >
            <div className="container h-100">
              <div className="row align-items-center">
                <div className="col-sm col-md-12 col-lg-12 text-center">
                  <div
                    className="welcome_text_area m-top-3"
                    style={{
                      width: "100%",
                      paddingBottom: "35px",
                      paddingTop: "35px",
                      marginBottom: "0px",
                    }}
                  >
                    <h3 className="fonts-shadow-into-light text-white">
                      <b>Événements récents</b>
                    </h3>
                  </div>
                </div>
              </div>
            </div>
          </section>
        </div>
      )}
    </>
  );
};

export default Event;

Upvotes: 2

Views: 1424

Answers (1)

Alan
Alan

Reputation: 46873

The resetting of your store state is caused by a combination of two issues:

First, as you do not hydrating your React Store's state based on the current URL, you must somehow save and load your Store's state to preserve it between page loads.

You can emulate this problem by simply copying and pasting the URL to a new browser window; you'll notice the store state is reset. There are a number of ways to store state, and you may wish to use either sessionStorage which remains for the duration your app is on the browser's tab, or localStorage which remains until your app clears it.

Second, the reason you are getting page loads when you don't expect to, is that it appears you are not using React Router correctly.

You are using Bootstrap's Navbar Link, which behaves like a normal <a> anchor tag. Click on the Nav.Link instructs your browser to make an HTTP GET call, and does a pageload which resets the store.

Instead you need to override the Bootstrap Nav Link component to instead use React Routers Link component, which will not do a page load, and instead load the correct React module.

https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage https://reactrouter.com/web/api/Link

Upvotes: 3

Related Questions