useNavigate Hook with React Testing Library 
        
         
        Editor’s note: This article was last updated by Rahul Chhodde on 4 May 2023 to include information the React fireEvent and userEvent Hooks, as well as testing the React query parameters.
 
React Testing Library is a lightweight solution that provides a virtual DOM to interact with and verify the behavior of a React component. Rather than work like a test runner, this testing library requires a tool like Jest to implement automated testing in React.
Using React Testing Library, popularly known as RTL in the community, is the recommended way to test your apps because it is actively maintained, well-documented, fast, flexible, and powerful enough to write comprehensive and reliable tests.
From React 18 onwards, React Hook Testing Library is included in the React Testing Library, and you can access it only through RTL. Learn more here.
In this article, we will cover testing scenarios of the useNavigate Hook from React Router 6 with RTL and Jest. We will unit test the routes and briefly discuss the different features that RTL offers to simplify the process of making components route-aware.
Jump ahead:
useNavigate Hook
useNavigate HookuseLocationfireEvent and userEvent methodsThe Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
useNavigate HookReact Router v6+ now uses the useNavigate Hook instead of the useHistory Hook. You can use useNavigate to go to a specific path or move back and forth in the browser history.
To add routes to your React app, you need to install the react-router-dom package. Once you have installed the package, you can import the Route component from it. The Route component takes two props: path and component. The path prop is the URL path that the route should match, and the component prop is the component that should be rendered when the route matches.
For example, the following code would add a route that matches the / path and renders the Home component:
import { Routes, Route } from "react-router-dom";
import { Home } from "./components/Home";
import { About } from "./components/About";
function App() {
  return (
    <>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </>
  );
}
export default App;
Let’s implement the useNavigate Hook. The example below shows how easy it is to navigate to other routes by using the useNavigate Hook:
import { useNavigate } from "react-router-dom";
function HomeButton() {
  const navigate = useNavigate();
  function handleClick() {
    navigate("/home");
  }
  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
Here is the live, working version of our project, which also includes the rest of the examples we covered in this article. See it on CodeSandbox here.
If you add { replace: true } as a second argument when using the useNavigate Hook, it works like the older history.replace method. To move back and forth in the history stack, use the following approach:
function HomeButton() {
  const navigate = useNavigate();
  const goBack() => navigate(-1);
  const goForward() => navigate(1);
}
useNavigate Hook with jest.mockAvoid using jest.mock to test React routes, as React Testing Library offers various methods to test routes without mocking. You can use the render method to isolate a route, the getBy* method to locate elements in the rendered page, and the fireEvent and userEvent Hooks to trigger different events.
useNavigate HookAs discussed before, React Router 6 and above now uses the useNavigate Hook instead of the useHistory Hook. You can no longer set the history prop to the router anymore. The history API is buggy and must have been discontinued in the newer version of React in favor of simplifying the complicated routing practices, so relying on it for routing is not a good idea.
Here’s a straightforward application to show you how to test routes with useNavigate. The application has different route components, and we used RTL and Jest features to test each one:
import { fireEvent, render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { MemoryRouter, BrowserRouter } from "react-router-dom";
import { About } from "./About";
describe("Demonstrating some useNavigate() tests ", () => {
  it("Renders the About component", () => {
    const { getByText } = render(
      <BrowserRouter>
        <About />
      </BrowserRouter>
    );
    const button = getByText(/contact us/i);
    expect(button).toBeInTheDocument();
    fireEvent.click(button);
  });
});
The above is a test component for the “About” section of our app. Keep in mind that all test components must be in the same directory as the original component so that Jest can detect our tests.
We use the describe and it methods from Jest to describe our tests and add some sample assertions. To locate an element with a specific text fragment from the rendered component, we use the RTL getByText utility. If the text fragment is not found, you’ll see an error while testing.
Next, we use fireEvent to click the selected button element. You can customize these tests further to fit your own needs.
useLocationWe now know how to test the regular React routes with RTL and Jest. Let’s test a route with query parameters with the help of the useLocation Hook.
We can grab the current URL with the useLocation Hook, then get the query string and extract the value from the query parameter using URLSearchParams, which is part of the Web API and Node.js API:
import { useLocation } from "react-router-dom";
const QueryParamComponent = () => {
  const location = useLocation();
  const id = new URLSearchParams(location.search).get("id");
  return (
    <div>
      <h1>Query Parameter Component</h1>
      <p>ID: {id}</p>
    </div>
  );
};
export default QueryParamComponent;
After extracting the value of the id query parameter from the URL, we added it to the resulting DOM element of this component. Now, let’s add a test for this:
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import QueryParamComponent from "./QueryParamComponent";
import "@testing-library/jest-dom";
describe("MyComponent", () => {
  it("renders the ID query parameter from the URL", () => {
    render(
      <MemoryRouter initialEntries={["/qpc?id=123"]}>
          <QueryParamComponent />
      </MemoryRouter>
    );
    expect(screen.getByText("ID: 123")).toBeInTheDocument();
  });
});
In the above code, we used MemoryRouter to create a mock router that we could use to test the behavior of the QueryParamComponent when it receives a query parameter through the location prop. We set its initial path to /query with an id query parameter so that our component would receive this information when it was rendered. Again, you can see this for yourself in the CodeSandbox demo’s tests.
fireEvent and userEvent methodsThe fireEvent method can dispatch any DOM event to an element, which helps test how components respond to events. For instance, you can use it to test a button that logs an input field’s value when clicked.
In contrast, userEvent is a simpler method that mimics how users interact with a component. This is helpful when testing components designed for humans, such as a login form:
...
describe("Login component", () => {
  it("Filling details and clicking buttons in a login gorm", async () => {
    render(
      <BrowserRouter>
        <Login />
      </BrowserRouter>
    );
    userEvent.type(screen.getByLabelText("Username"), "hello");
    userEvent.type(screen.getByLabelText("Password"), "123");
    userEvent.click(screen.getByRole("button", { name: "Submit" }));
  });
});
To use the userEvent object, you need to install the @testing-library/user-event package as an additional dependency.
As I mentioned earlier, you don’t need to use the @testing-library/react-hooks library anymore with React 18 and above. The RTL now includes built-in methods for testing hooks.
It’s fairly easy to test different hooks using the RTL built-in methods only. Here is an example of how to test a custom hook created with useState, demonstrating a dynamic count component that increments with a button click:
describe("CountComponent", () => {
  it("SHOULD render the expected Count Component", () => {
    const { getByText } = render(
      <BrowserRouter>
        <CountComponent />
      </BrowserRouter>
    );
    const heading = getByText(/the count component/i);
    const count = getByText(/the count is 0/i);
    expect(heading).toBeInTheDocument();
    expect(count).toBeInTheDocument();
  });
  it("SHOULD increment the count when the button is CLICKED", () => {
    const { getByText } = render(
      <BrowserRouter>
        <CountComponent />
      </BrowserRouter>
    );
    const button = getByText(/increment Count/i);
    const count = getByText(/the count is 0/i);
    fireEvent.click(button);
    expect(count).toHaveTextContent(/the count is 1/i");
  });
});
This component and its test are only available in the CodeSandbox example.
With the ever-changing React ecosystem, there are new tools available to help you write better tests. I don’t recommend using Jest mocks to test routes, as this can give the illusion of testing without actually testing anything.
In this article, we explored how to test the useNavigate Hook that was introduced in React Router v6. I hope you enjoyed this article, and feel free to leave a comment if you have any questions. Happy testing!
            Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not
            server-side
            
$ npm i --save logrocket 
// Code:
import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
                    
                    
// Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
                    
                    
line-clamp to trim lines of textMaster the CSS line-clamp property. Learn how to truncate text lines, ensure cross-browser compatibility, and avoid hidden UX pitfalls when designing modern web layouts.

Discover seven custom React Hooks that will simplify your web development process and make you a faster, better, more efficient developer.

Promise.all still relevant in 2025?In 2025, async JavaScript looks very different. With tools like Promise.any, Promise.allSettled, and Array.fromAsync, many developers wonder if Promise.all is still worth it. The short answer is yes — but only if you know when and why to use it.

Discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the October 29th issue.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now 
         
         
        
3 Replies to "Testing the React Router <code>useNavigate</code> Hook with React Testing Library"
It seems the history prop does not exist on Router in v6
This. I was enthusiastic when I read the article was written in 2022, hoping that it would cover react router v6.
How to write tests if a react component contains both useLocation and useNavigate