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 />} />
...