Laakal
Laakal

Reputation: 687

React router 6 never unmount component when URL parameter changes

We have a problem with the react router v6. When the URL parameters change, it is already using the mount component. Never unmount and mount the component.

Produced code example - if switching between link 1 and link 2(url parameter (id) changes), the Link component never unmount and mount: https://stackblitz.com/edit/github-agqlf5-gohmbu?file=src/routes/link.jsx

So how do we get it to be unmount and mount component when the url parameter changes?

Upvotes: 7

Views: 4026

Answers (1)

Drew Reese
Drew Reese

Reputation: 202751

This is by-design. If you look at the Route rendering the Invoices component

<Route path="link/:id" element={<Invoices />} />

There is nothing here to cause (a) the Route to remount, and (b) the routed component Invoices to remount. If the route path updates it will only trigger a rerender of the routed component, only values in the routing context have changed really. Think of this more like an update to props triggering a component to rerender, not remount.

If the routed component needs to "listen" to and respond to route param changes then it should use a useEffect hook to issue any side-effects.

Example:

import { Outlet, useParams } from 'react-router-dom';

export default function Invoices() {
  const { id } = useParams();

  React.useEffect(() => {
    console.log('mount');
    return () => console.log('unmount');
  }, []);

  React.useEffect(() => {
    console.log("Route parameter changed", { id });
  }, [id]);

  return (
    <div style={{ display: 'flex', paddingTop: '1rem' }}>
      <nav>Invoice ID: {id}</nav>
      <Outlet />
    </div>
  );
}

If you really want to remount the routed component then create a wrapper component that reads the id route path param and sets a React key on the routed component. The InvoicesWrapper will remain mounted but when the id route param updates the Invoices component will remount since it has a new React key.

Example:

const InvoicesWrapper = () => {
  const { id } = useParams();

  return <Invoices key={id} />
};

...

...
<Route path="link/:id" element={<InvoicesWrapper />} />
...

Upvotes: 12

Related Questions