4

Why does the state reset in react component when changing between pages using react-router?


As I understand it, you should be able to switch between routes (components) using react-router as long as you use the 'react' way of changing, ie. <Link to="/otherRoute" />. This is not the case for me and I do not see why. Here is the code:

App.js


import RoutesComp from "./RoutesComp";
import { Link } from "react-router-dom";

function App() {
  return (
    <div className="App">
      <p>
        <Link to="/state">State</Link>
      </p>
      <p>
        <Link to="/dummy">dummy</Link>
      </p>
      <RoutesComp />
    </div>
  );
}

export default App;

StateComp.js

import React, { useState } from "react";

const StateComp = () => {
  const [counter, setCounter] = useState(0);

  return (
    <>
      <button onClick={() => setCounter((prev) => prev + 1)}>click to increment</button>
      <p>{counter}</p>{" "}
    </>
  );
};

export default StateComp

RoutesComp.js

import React from "react";

import { Route, Switch } from "react-router-dom";
import StateComp from "./StateComp";
import Dummy from "./Dummy";

const RoutesComp = (props) => {
  return (
    <>
      <Switch>
        <Route path="/state" render={() => <StateComp />} />
        <Route path="/dummy" render={() => <Dummy />} />

// I also tried it the original way
        {/* <Route path="/state">
          <StateComp />
        </Route>
        <Route path="/dummy">
          <Dummy />
        </Route> */}
      </Switch>
    </>
  );
};

export default RoutesComp;

This produces the following:

enter image description here

When you click on the increment button, the count goes up, but when you go to the 'dummy' page and come back to the 'state' page, the counter is at 0 again.

From my research, react router difference between component and render it looks like the state will be reset if you create routes using

<Route path="/state">
    <StateComp />
</Route>
<Route path="/dummy">
    <Dummy />
</Route>

However, it seems like the way to get the state to not be reset is to use render={() => <Comp/>}. I tried that as well and that did not work.

Can anyone offer some insight as to what I'm doing wrong?


EDIT: Dependencies/Versions

"dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router": "^5.0.0",
    "react-router-dom": "^5.0.0",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
3
  • Hi, I've did a little digging around this topic. Looks like this answers your question: stackoverflow.com/a/45930922/5281962 . In short, don't use Switch component and use the children prop for the Route component. Here's an example that I have implemented: codesandbox.io/s/persist-state-react-router-1t4bl Commented Oct 16, 2021 at 16:40
  • @Cherubim thanks for this guidance. This helps me out. Though, I am disappointed that there seems to be no built in way to do this with react-router. I guess one way is to lift the state up outside of the component that rerenders using redux or the context API. Commented Oct 17, 2021 at 2:33
  • @Cherubim Please feel free to put your comment as an answer and I will gladly select it as the best answer Commented Oct 17, 2021 at 2:34

1 Answer 1

3

The Switch component only ever renders a single route, the earliest match wins. All the components whose routes do not get matched are unmounted.

To avoid this, you need to move you Route components outside of the Switch component and use the children property to render your component.

Here's an example that implements the above mentioned approach: example codesandbox link

Some other workarounds include:

  1. Lifting up your state using either redux or useContext API
  2. use the url parameters to store the state(not suitable for complex components)

Helpful links:

  1. React-router: never unmount a component on a route once mounted, even if route change
  2. How to persist state across react router transitions
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.