Skip to content

useParams() shows different behaviour between Routes and RouteProvider when using react-router 7.1.5 in library mode #12939

Closed
@almilo

Description

@almilo

I'm using React Router as a...

library

Reproduction

Based on this useParams() test:

describe("when the path has some params", () => {
I created the following tests to show the different behaviour:

import '@testing-library/jest-dom/vitest';
import { cleanup, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it } from 'vitest';
import { createMemoryRouter, MemoryRouter, Route, Routes, useParams } from 'react-router';
import { RouterProvider } from 'react-router/dom';

describe('useParams', () => {
  afterEach(cleanup);

  function ShowParams() {
    return <pre data-test="params">{JSON.stringify(useParams())}</pre>;
  }

  it('with routes shows the url params', async () => {
    render(
      <MemoryRouter initialEntries={['/blog/react-router']}>
        <Routes>
          <Route path="/blog/:slug" element={<ShowParams />} />
        </Routes>
      </MemoryRouter>,
    );

    expect(await screen.findByTestId('params')).toMatchInlineSnapshot(`
        <pre
          data-test="params"
        >
          {"slug":"react-router"}
        </pre>
      `);
  });

  it('with route provider shows the url params', async () => {
    const router = createMemoryRouter(
      [
        {
          path: '/blog/:slug',
          element: <ShowParams />,
        },
      ],
      {
        initialEntries: ['/blog/react-router'],
      },
    );

    render(<RouterProvider router={router} />);

    expect(await screen.findByTestId('params')).toMatchInlineSnapshot(`
      <pre
        data-test="params"
      >
        {"slug":"react-router"}
      </pre>
    `);
  });
});

System Info

Node version: v20.14.0

Package versions used:
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router": "^7.1.5",

    "@testing-library/jest-dom": "^6.5.0",
    "@testing-library/react": "^14.3.1",
    "@testing-library/user-event": "^14.5.2",
    "vitest": "^1.6.0"

Used Package Manager

npm

Expected Behavior

Hi React Router Team,

While following the migration guide in https://reactrouter.com/upgrading/v6 and after switching from v6.x to v7.x a non-documented breaking change in useParams() seems to be reproducible in unit tests. The current react-router useParams() unit tests do not cover the usage of RouteProvider explicitly and also use the deprecated "react-test-renderer" package. I would expect to have this behaviour mentioned in the migration guide (if not a bug) and some up-to-date tests to show the required changes between RouteProvider and createBrowserRouter().

Thanks a lot in advance!

Actual Behavior

When executing the test above with "react-router@7.1.5", the test using the route provider fails as useParams() does not return any parameters:
Image
Image

When executing the test above with "react-router@6.29.0" and "react-router-dom@6.29.0", both tests pass:
Image

Using all future flags does not fix the failing test either:

    const router = createMemoryRouter(
      [
        {
          path: '/blog/:slug',
          element: <ShowParams />,
        },
      ],
      {
        initialEntries: ['/blog/react-router'],
        future: {
          v7_relativeSplatPath: true,
          v7_startTransition: true,
          v7_fetcherPersist: true,
          v7_normalizeFormMethod: true,
          v7_partialHydration: true,
          v7_skipActionErrorRevalidation: true,
        },
      },
    );

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions