-1

Is there a way to stop the route from unmounting? In my app I would need to keep react state between switching the routes.

Here you can see that, if we change route then home respective route component will mount and unmount. I don't want.

CODESANDBOX DEMO

I've looked in

How can I prevent the unmount in React Components?

How can I prevent React from unmounting/remounting a component?

but doesn't work for me.

index.js

import React from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import First from "./routes/First";
import Second from "./routes/Second";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <BrowserRouter>
    <Routes>
      <Route path="" element={<App />} />
      <Route path="first" element={<First />} />
      <Route path="second" element={<Second />} />
    </Routes>
  </BrowserRouter>
);

App.js

import * as React from "react";
import { Link } from "react-router-dom";

export default function App() {
  return (
    <div>
      <h1>Prevent Routing</h1>
      <nav
        style={{
          borderBottom: "solid 1px",
          paddingBottom: "1rem"
        }}
      >
        <Link to="/first">First</Link> |<Link to="/second">Second</Link>
      </nav>
    </div>
  );
}

First.js

import * as React from "react";
import { useEffect } from "react";
import { Link } from "react-router-dom";

export default function First() {
  useEffect(() => {
    console.log("mounted First");

    return () => console.log("unmounted First");
  }, []);

  return (
    <main style={{ padding: "1rem 0" }}>
      <Link to="/">Home</Link>
      <h2>First</h2>
    </main>
  );
}

Second.js

import * as React from "react";
import { useEffect } from "react";
import { Link } from "react-router-dom";

export default function Second() {
  useEffect(() => {
    console.log("mounted Second");

    return () => console.log("unmounted Second");
  }, []);

  return (
    <main style={{ padding: "1rem 0" }}>
      <Link to="/">Home</Link>
      <h2>Second</h2>
    </main>
  );
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
DecPK
  • 24,537
  • 6
  • 26
  • 42
  • No, not really. This is how `react-router-dom` works. It mounts and unmounts the routed components as the routes are matched and rendered. If this isn't the desired behavior then perhaps `RRD` isn't the correct tool for the job. What exactly is the use case by keeping these components mounted or issue with unmounting when they are no longer being matched and rendered to the DOM? – Drew Reese Jan 09 '23 at 18:43

1 Answers1

1

React Router will always unmount the component when it's not matched by a path.


You could fix this by combining both Components with a double route, each component can determine what he will render based on the current path.

So the main routing will look something like:

<Route path={[ '/first', '/second' ]}>
    <First {...{}} />
    <Second {...{}} />
</Route>

Then use useLocation in the component to toggle the render:

import { useLocation } from "react-router-dom";

function First(props) {

    const location = useLocation();

    if (location.pathname !== '/first') {
        return null
    }
}
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • I've done as you suggested but I'm getting this error, `[First] is not a component. All component children of must be a or ` [codesandbox](https://codesandbox.io/s/weathered-framework-exx6k3?file=/src/index.js). Tried to wrap it with `React.Fragment` and also with `` then also getting same error – DecPK Jan 09 '23 at 11:16
  • OP is using `react-router-dom@6` but your answer here uses `react-router-dom@5` `Route` component APIs/syntax. It won't work as you as expecting. – Drew Reese Jan 09 '23 at 18:41