How to Update MemoryRouter in React
React Router’s MemoryRouter is a routing component that
stores its locations in memory rather than the browser’s address bar,
making it ideal for testing and non-browser environments like React
Native. This article explains how to update and navigate within a
MemoryRouter programmatically using the
useNavigate hook, configure its initial state using props,
and trigger routing updates during component testing.
Programmatic Navigation with useNavigate
The standard way to update the active route inside a
MemoryRouter is by using the useNavigate hook.
Since MemoryRouter behaves like a standard router
internally, any child component can trigger navigation updates.
Here is a basic example of how to update the route programmatically:
import { MemoryRouter, Routes, Route, useNavigate } from 'react-router-dom';
function NavigationTrigger() {
const navigate = useNavigate();
return (
<button onClick={() => navigate('/dashboard')}>
Go to Dashboard
</button>
);
}
export default function App() {
return (
<MemoryRouter initialEntries={['/']}>
<Routes>
<Route path="/" element={<NavigationTrigger />} />
<Route path="/dashboard" element={<h1>Dashboard Page</h1>} />
</Routes>
</MemoryRouter>
);
}When the button is clicked, the useNavigate hook updates
the internal history stack of the MemoryRouter, changing
the rendered component to the /dashboard route.
Updating the Initial State with Props
To dynamically update or set the starting location of the
MemoryRouter (such as in unit tests or when mounting a
component), use the initialEntries and
initialIndex props.
initialEntries: An array of URLs that represent the history stack.initialIndex: The index in theinitialEntriesarray that the router should start on.
<MemoryRouter initialEntries={['/home', '/profile', '/settings']} initialIndex={2}>
<App />
</MemoryRouter>In this setup, the router starts at /settings (index 2).
If you programmatically trigger a back action, the router will navigate
to /profile.
Updating MemoryRouter in Unit Tests
When testing React components with libraries like React Testing
Library, you often need to verify that a routing update occurred.
Because MemoryRouter does not change the browser’s URL bar,
you must assert against changes in the rendered DOM.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
test('navigates to dashboard on button click', async () => {
render(<App />);
// Verify initial route content
expect(screen.getByText(/Go to Dashboard/i)).toBeInTheDocument();
// Simulate user clicking the navigation button
await userEvent.click(screen.getByRole('button', { name: /Go to Dashboard/i }));
// Verify the MemoryRouter updated and rendered the new route
expect(screen.getByText(/Dashboard Page/i)).toBeInTheDocument();
});By interacting with the UI elements, you trigger the internal state
updates of the MemoryRouter, allowing you to assert that
your application navigates correctly.