Skip to content

docs(react-router): fixes react router v6 examples, removes outdated comments #1107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 5, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 63 additions & 59 deletions docs/example-react-router.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ id: example-react-router
title: React Router
---

The example below now supports React Router v6.
This example demonstrates React Router v6. For previous versions see below.

```jsx
// app.js
import React from 'react'
import {Link, Route, Switch, useLocation} from 'react-router-dom'
import {Link, Route, Routes, useLocation} from 'react-router-dom'

const About = () => <div>You are on the about page</div>
const Home = () => <div>You are home</div>
Expand All @@ -26,19 +26,13 @@ export const App = () => (

<Link to="/about">About</Link>

<Switch>
<Route exact path="/">
<Home />
</Route>
<Routes>
<Route exact path="/" element={<Home />} />

<Route path="/about">
<About />
</Route>
<Route path="/about" element={<About />} />

<Route>
<NoMatch />
</Route>
</Switch>
<Route path="*" element={<NoMatch />} />
</Routes>

<LocationDisplay />
</div>
Expand All @@ -49,79 +43,55 @@ export const App = () => (
// app.test.js
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {createMemoryHistory} from 'history'
import React from 'react'
import {Router} from 'react-router-dom'

import '@testing-library/jest-dom'

import {App, LocationDisplay} from './app'
import {BrowserRouter, MemoryRouter} from 'react-router-dom'

test('full app rendering/navigating', async () => {
const history = createMemoryHistory()
render(
<Router location={history.location} navigator={history}>
<App />
</Router>,
)
render(<App />, {wrapper: BrowserRouter})
const user = userEvent.setup()
// verify page content for expected route
// often you'd use a data-testid or role query, but this is also possible

// verify page content for default route
expect(screen.getByText(/you are home/i)).toBeInTheDocument()

// verify page content for expected route after navigating
await user.click(screen.getByText(/about/i))

// check that the content changed to the new page
expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
})

test('landing on a bad page', () => {
const history = createMemoryHistory()
history.push('/some/bad/route')
const badRoute = '/some/bad/route'

// use <MemoryRouter> when you want to manually control the history
render(
<Router location={history.location} navigator={history}>
<MemoryRouter initialEntries={[badRoute]}>
<App />
</Router>,
</MemoryRouter>,
)

// verify navigation to "no match" route
expect(screen.getByText(/no match/i)).toBeInTheDocument()
})

test('rendering a component that uses useLocation', () => {
const history = createMemoryHistory()
const route = '/some-route'
history.push(route)

// use <MemoryRouter> when you want to manually control the history
render(
<Router location={history.location} navigator={history}>
<MemoryRouter initialEntries={[route]}>
<LocationDisplay />
</Router>,
</MemoryRouter>,
)

// verify location display is rendered
expect(screen.getByTestId('location-display')).toHaveTextContent(route)
})
```

## Reducing boilerplate

1. You can use the `wrapper` option to wrap a `MemoryRouter` around the
component you want to render.
`MemoryRouter` works when you don't need access to the history object itself
in the test, but just need the components to be able to render and
navigate.
If you _do_ need to change the history, you could use `BrowserRouter`.

```jsx
import {MemoryRouter} from 'react-router-dom'

test('full app rendering/navigating', () => {
render(<App />, {wrapper: MemoryRouter})

// verify page content for expected route
expect(screen.getByText(/you are home/i)).toBeInTheDocument()
})
```

2. If you find yourself adding Router components to your tests a lot, you may
1. If you find yourself adding Router components to your tests a lot, you may
want to create a helper function that wraps around `render`.

```jsx
Expand Down Expand Up @@ -161,16 +131,50 @@ test('rendering a component that uses useLocation', () => {
})
```

## Testing Library and React Router v5
## Testing Library and React Router v5

In React Router v5, you need to pass the history object as a whole to the Route component.
In React Router v5, you need to pass the history object as a whole to the Route
component.

```jsx
test('full app rendering/navigating', () => {
// app.test.js
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {createMemoryHistory} from 'history'
import React from 'react'
import {Router} from 'react-router-dom'
import '@testing-library/jest-dom'
import {App} from './app'

// React Router v5

test('full app rendering/navigating', async () => {
const history = createMemoryHistory()
render(
<Router history={history}>
<Router location={history.location} navigator={history}>
<App />
</Router>,
)
```
const user = userEvent.setup()
// verify page content for expected route
// often you'd use a data-testid or role query, but this is also possible
expect(screen.getByText(/you are home/i)).toBeInTheDocument()

await user.click(screen.getByText(/about/i))

// check that the content changed to the new page
expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
})

test('landing on a bad page', () => {
const history = createMemoryHistory()
history.push('/some/bad/route')
render(
<Router location={history.location} navigator={history}>
<App />
</Router>,
)

expect(screen.getByText(/no match/i)).toBeInTheDocument()
})
```