diff --git a/docs/example-react-router.mdx b/docs/example-react-router.mdx index 530bb5f3b..776675787 100644 --- a/docs/example-react-router.mdx +++ b/docs/example-react-router.mdx @@ -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) { + 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 }) { + await sleep(); + let formData = await request.formData(); + let name = formData.get('name'); + console.log(name); + // Call an async method to add and so on + return redirect('/'); +} + +export const About = () => { + return ( + <> +
You are on the about page
+
+ + +
+ + ); +}; + +export const Home = () => { + let data = useLoaderData(); + return
You are {data.message}
; +}; + +export const NoMatch = () =>
No match
; + +export const LocationDisplay = () => { + const location = useLocation(); + + return
{location.pathname}
; +}; + +export const Layout = () => ( +
+ Home + About + + +
+); + +export const routes = [ + { + path: '/', + element: , + children: [ + { + index: true, + element: , + loader: homeLoader, + }, + { + path: '/about', + element: , + action: aboutAction, + }, + { + path: '*', + element: , + }, + ], + }, +]; + +const router = createBrowserRouter(routes); + +const App = () => ; + +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(); + + 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(); + + // 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(); + + // 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) + +## Testing Library and React Router v6 ```jsx // app.js