-
Notifications
You must be signed in to change notification settings - Fork 721
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
Fixes #1265 Updated example for react-router v6.4 #1266
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,159 @@ id: example-react-router | |
title: React Router | ||
--- | ||
|
||
This example demonstrates React Router v6. For previous versions see below. | ||
This example demonstrates React Router v6.4 and above. For previous versions see below. | ||
|
||
```jsx | ||
// App.jsx | ||
import { | ||
createBrowserRouter, | ||
Form, | ||
Link, | ||
Outlet, | ||
redirect, | ||
RouterProvider, | ||
useLoaderData, | ||
useLocation, | ||
} from 'react-router-dom'; | ||
|
||
// Method to introduce an artificial delay | ||
export function sleep(n = 500) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you clean this example up please? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually this is a modified form of the example in react router examples source code I wanted this to be close to the original doc and hence left it. |
||
return new Promise((r) => setTimeout(r, n)); | ||
} | ||
|
||
// Loader to return after a small delay | ||
export async function homeLoader() { | ||
await sleep(); | ||
return { | ||
message: 'home', | ||
}; | ||
} | ||
|
||
// Action to get user input | ||
export async function aboutAction({ request }) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this can also be left out, or there should be a test that verifies its behavior. |
||
await sleep(); | ||
let formData = await request.formData(); | ||
let name = formData.get('name'); | ||
console.log(name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
// Call an async method to add and so on | ||
return redirect('/'); | ||
} | ||
|
||
export const About = () => { | ||
return ( | ||
<> | ||
<div>You are on the about page</div> | ||
<Form method="post"> | ||
<input name="person" placeholder="Name" /> | ||
<button type="submit">Submit</button> | ||
</Form> | ||
</> | ||
); | ||
}; | ||
|
||
export const Home = () => { | ||
let data = useLoaderData(); | ||
return <div>You are {data.message}</div>; | ||
}; | ||
|
||
export const NoMatch = () => <div>No match</div>; | ||
|
||
export const LocationDisplay = () => { | ||
const location = useLocation(); | ||
|
||
return <div data-testid="location-display">{location.pathname}</div>; | ||
}; | ||
|
||
export const Layout = () => ( | ||
<div> | ||
<Link to="/">Home</Link> | ||
<Link to="/about">About</Link> | ||
<Outlet /> | ||
<LocationDisplay /> | ||
</div> | ||
); | ||
|
||
export const routes = [ | ||
{ | ||
path: '/', | ||
element: <Layout />, | ||
children: [ | ||
{ | ||
index: true, | ||
element: <Home />, | ||
loader: homeLoader, | ||
}, | ||
{ | ||
path: '/about', | ||
element: <About />, | ||
action: aboutAction, | ||
}, | ||
{ | ||
path: '*', | ||
element: <NoMatch />, | ||
}, | ||
], | ||
}, | ||
]; | ||
|
||
const router = createBrowserRouter(routes); | ||
|
||
const App = () => <RouterProvider router={router}></RouterProvider>; | ||
|
||
export default App; | ||
``` | ||
|
||
```jsx | ||
// App.test.jsx | ||
import { render, screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import React from 'react'; | ||
import '@testing-library/jest-dom'; | ||
import { | ||
createBrowserRouter, | ||
createMemoryRouter, | ||
RouterProvider, | ||
} from 'react-router-dom'; | ||
import { routes } from './App'; | ||
|
||
test('full app rendering/navigating', async () => { | ||
const router = createBrowserRouter(routes); | ||
render(<RouterProvider router={router}></RouterProvider>); | ||
|
||
const user = userEvent.setup(); | ||
// We need to wait for the loader data and then assert presence | ||
expect(await screen.findByText(/you are home/i)).toBeInTheDocument(); | ||
|
||
// verify page content for expected route after navigating | ||
await user.click(screen.getByText(/about/i)); | ||
expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument(); | ||
}); | ||
|
||
test('landing on a bad page', () => { | ||
const badRoute = '/some/bad/route'; | ||
const router = createMemoryRouter(routes, { initialEntries: [badRoute] }); | ||
|
||
// use createMemoryRouter when you want to manually control the history | ||
render(<RouterProvider router={router}></RouterProvider>); | ||
|
||
// verify navigation to "no match" route | ||
expect(screen.getByText(/no match/i)).toBeInTheDocument(); | ||
}); | ||
|
||
test('rendering a component that uses useLocation', () => { | ||
const route = '/some-route'; | ||
const router = createMemoryRouter(routes, { initialEntries: [route] }); | ||
|
||
// use createMemoryRouter when you want to manually control the history | ||
render(<RouterProvider router={router}></RouterProvider>); | ||
|
||
// verify location display is rendered | ||
expect(screen.getByTestId('location-display')).toHaveTextContent(route); | ||
}); | ||
``` | ||
Refer to [this working example](https://stackblitz.com/edit/vitejs-vite-dnutcg?file=src%2FApp.test.jsx,src%2FApp.jsx) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because other examples don't have a stackblitz I was thinking on removing this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Te reason for having that was, I couldn't get other examples to run without making code changes |
||
|
||
## Testing Library and React Router v6 | ||
|
||
```jsx | ||
// app.js | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not very familiar with this, but I assume
createBrowserRouter
is added in v6.4?