[Bug]: `Navigate` causes an infinite loop if it remains mounted after navigation

See original GitHub issue

What version of React Router are you using?

6.2.1

Steps to Reproduce

In a previous version of React router we could test components that used Redirect in isolation without needing to mock the implementation details of react-router like below:

const ErrorRedirect = ({ error }) =>  {
    if(error) {
       return <Redirect to="/error" />
   }
   return null;
}

it('redirects to the error route if it receives an error', () => {
    const history = createMemoryHistory();
    render(
        <HistoryRouter history={history}>
            <ErrorRedirect error={new Error()} />
         </HistoryRouter>
    );
    expect(history.location.pathname).toBe('/error');
});

When switching Redirect for a Navigate component in v6 this same test causes the app to crash. This is because Navigate causes an infinite loop if it remains mounted after the navigation has taken place.

Expected Behavior

Would expect the location to change but the component to only rerender once.

Actual Behavior

Navigate causes an infinite loop and the process crashes.

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:4
  • Comments:11 (2 by maintainers)

github_iconTop GitHub Comments

5reactions
jordan-burnettcommented, May 24, 2022

As a workaround we’ve implemented the fix in https://github.com/remix-run/react-router/pull/8734 as a standalone component. You should be able to replace the built-in Navigate component with something like the below, or just use useNavigate directly in your components until then.

import type { NavigateProps } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';

export const Navigate: React.FC<NavigateProps> = ({ to, replace, state }) => {
  const navigate = useNavigate();
  const navigateRef = useRef(navigate);

  useEffect(() => {
    navigateRef.current = navigate;
  }, [navigate]);

  useEffect(() => {
    navigateRef.current(to, { replace, state });
  }, [to, replace, state]);

  return null;
};
1reaction
shamseerahammedmcommented, Oct 25, 2022

How do u get this working with createBrowserRouter ? its causing infinite loop. Tried solution by @jordan-burnett , but then it fixes inifinte loop but nothing is rendering on page, just shows a blank page

const getRoutes = (isUserLoggedIn : boolean) => {
  console.log('isUserLoggedIn',isUserLoggedIn);
  const router = createBrowserRouter([
    {
      path: '/',
      element: isUserLoggedIn ? <Navigate to="/dashboard" replace={true} /> : <LoginPage/>,
      children: [
        {
          path: '/dashboard',
          element: (
            <DashboardPage/>
          ),
        },
      ],
    },
  ]);
  return router;
};
 <RouterProvider router={getRoutes(isUserLoggedIn)} />
Read more comments on GitHub >

github_iconTop Results From Across the Web

Jetpack Compose Navigation endless loop - Stack Overflow
1 Answer 1 ... It looks like a similar issue like this and this. Based on the official Docs,. You should only call...
Read more >
useHooks - Easy to understand React Hook recipes
If that object is a useEffect dependency then it's going to cause the effect to fire on every render, which can lead to...
Read more >
Handling Mounting And Unmounting Of Navigation Routes In ...
Let's look at how to mount and unmount navigation stack based on a met ... Like localStorage on the web, it is a...
Read more >
How to work with React the right way to avoid some common ...
Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application....
Read more >
React useEffect hook with code examples
This may cause inconsistency, weird side-effects, or freezing your app from an infinite loop. Let's optimize this code a little bit more. React...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found