remix-run / react-router

Declarative routing for React
https://reactrouter.com
MIT License
53.3k stars 10.33k forks source link

[Bug]: useNavigate is failing when running in react testing library on react-router v7 #12368

Closed kelsin closed 5 days ago

kelsin commented 5 days ago

What version of React Router are you using?

7.0.1

Steps to Reproduce

https://stackblitz.com/edit/vitejs-vite-9tur3x

I created this tiny example to show this error. This app just has two routes and a button to swap between them on each page using useNavigate. The app itself works with a memory router or a browser router.

The tests however don't run with either router. You can run the tests in the above environment with npm run test.

Here is a working version (all the same) on react-router v6.28.0: https://stackblitz.com/edit/vitejs-vite-sygeg8

Expected Behavior

The test is able to render the main page and read the text on it.

Actual Behavior

We get this error: Error: Uncaught [Error: useNavigate() may be used only in the context of a <Router> component.]

The app doesn't render so the test doesn't pass.

Info

I saw this tonight while trying to update my react app from 6.28.0 to 7.0.1. This only occurs in tests in react testing library. My larger app behaves identically. This bug only happens in testing and regardless of if I use createMemoryRouter or createBrowserRouter.

jessemyers-lettuce commented 5 days ago

We see a similar error. It's not apparent using the dev server, only after a production build and deploy.

timdorr commented 5 days ago

Simple fix. Change your RouterProvider import to this:

import { RouterProvider } from 'react-router';
kelsin commented 5 days ago

Simple fix. Change your RouterProvider import to this:

import { RouterProvider } from 'react-router';

Sounds good. This ties into my other points here: https://github.com/remix-run/react-router/discussions/12370

Should update https://reactrouter.com/upgrading/v6#upgrade-to-v7 as well since that's where I was told to use the current import.

timdorr commented 5 days ago

Thanks, I added that now.

rothsandro commented 4 days ago

The tests run with jsdom so it's not a "not-DOM context" as mentioned in the docs. Importing from react-router breaks other use cases, e.g. when navigating with flushSync: true:

You provided the flushSync option to a router update, but you are not using the <RouterProvider> from react-router/dom so ReactDOM.flushSync() is unavailable.

teukuamru commented 3 days ago

Thanks, I added that now.

I'm not an expert in react-router but in that page, it is written that I need to install react-router-dom but the very next step I need to uninstall it? Is there any explanation to this?

Screenshot 2024-11-26 at 18 12 22

kelsin commented 3 days ago

I'm not an expert in react-router but in that page, it is written that I need to install react-router-dom but the very next step I need to uninstall it? Is there any explanation to this?

I'm not associated with the project, but I believe the intent is:

  1. You can upgrade to v7 - App Still Works
  2. You can change your source imports from react-router-dom to react-router - App Still Works
  3. You can uninstall and replace with the base package - App Still Works