MemoryRouter and StaticRouter

The remaining two routers exist for environments with no address bar. <MemoryRouter> keeps the history stack in a plain array. initialEntries seeds that array and initialIndex picks which entry is current, so a test can start at any URL — or mid-stack, with entries behind it, to assert that Back behaves. It is the router for Vitest 102,989 and React Testing Library 221,825 (React Testing Library), for Storybook 3,824 , and for React Native 36,878 .

Rendering a routed component in a testJSX
test('shows the product for the :sku in the URL', () => {
  render(
    <MemoryRouter initialEntries={['/cart', '/products/A-42']} initialIndex={1}>
      <Routes><Route path="/products/:sku" element={<Product />} /></Routes>
    </MemoryRouter>
  );
  expect(screen.getByRole('heading')).toHaveTextContent('A-42');
});

<StaticRouter> goes one step further: its location never changes at all. On the server there is exactly one URL per request and nobody clicking around, so a router that cannot navigate is the honest model. In an Express 24,430 handler you wrap the app in <StaticRouter location={req.url}> and pass that to renderToString.

It now takes only basename, location and children. The context object React Router 5 139,386 used to smuggle a status code or redirect target back out of the render is gone, so it cannot tell you the app wanted a 404 or a 302 — one reason server rendering has moved to the data routers of Data Routers.