Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Render hangs with unstable_HistoryRouter #8591

Closed
davesteinberg opened this issue Jan 19, 2022 · 2 comments
Closed

[Bug]: Render hangs with unstable_HistoryRouter #8591

davesteinberg opened this issue Jan 19, 2022 · 2 comments
Labels

Comments

@davesteinberg
Copy link

What version of React Router are you using?

6.2.1

Steps to Reproduce

I'm attempting to use the new unstable_HistoryRouter (thanks for it!) to move a project with a bunch of isolated component tests that check history effects over to React Router 6. I've noticed that a particular combination of React Router components seems to cause the render to hang: a Navigate nested inside a HistoryRouter, with no Routes/Route in between.

The same structure works fine with MemoryRouter and the equivalents also worked in 5.3.0.

I've created a minimal test case that illustrates the problem: https://github.com/davesteinberg/history-router-bug

Just clone, npm install, and npm test to see it.

To highlight the problem, here are the key pieces:

export function Page1() {
  return <div>This is page one.</div>;
}

export function Page2() {
  return <Navigate to="/1" replace />;
}

describe("with HistoryRouter", () => {
  test("page 2 redirects to page 1", () => {
    const history = createMemoryHistory();
    render(
      <HistoryRouter history={history}>
        <Page2 />
      </HistoryRouter>
    );

    expect(history.location.pathname).toBe("/1");
  });
});

There are three other test cases in App.test.js that do work, including the last one, which renders the same page component inside a MemoryRouter instead of a HistoryRouter.

Expected Behavior

The render succeeds and the tests pass.

Actual Behavior

The render loops infinitely and the following warning is displayed:

Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

@timdorr
Copy link
Member

timdorr commented Jan 19, 2022

You're rendering a component that renders a Navigate (your Page2 component), which is navigating and triggering a re-render of itself. That's what forms the infinite loop.

If you put that same Page2 component inside of your MemoryRouter tests, you'll see it does the exact same thing. You need to render a Routes, so the component goes away after navigating and doesn't form a loop.

@timdorr timdorr closed this as completed Jan 19, 2022
@davesteinberg
Copy link
Author

Wow, I bent my brain into a dumb circle with this. I convinced myself that it worked with MemoryRouter, but I had typo'ed in the test case and was rendering Page1 instead.

My starting point was that I was that these kinds of tests worked in v5, but that was with just Router (not MemoryRouter) which probably doesn't do much of anything when the location changes.

Apologies for the noise, and thanks for the quick pointer!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants