Skip to content
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

Warn Against Non-<Route> children of <Routes> #8238

Merged
merged 1 commit into from Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/react-router/__tests__/Routes-test.tsx
Expand Up @@ -4,12 +4,15 @@ import { MemoryRouter, Routes, Route } from "react-router";

describe("<Routes>", () => {
let consoleWarn: jest.SpyInstance;
let consoleError: jest.SpyInstance;
beforeEach(() => {
consoleWarn = jest.spyOn(console, "warn").mockImplementation(() => {});
consoleError = jest.spyOn(console, "error").mockImplementation(() => {});
});

afterEach(() => {
consoleWarn.mockRestore();
consoleError.mockRestore();
});

it("renders null and issues a warning when no routes match the URL", () => {
Expand Down Expand Up @@ -110,4 +113,36 @@ describe("<Routes>", () => {
</h1>
`);
});

it("throws if some <CustomRoute> is passed as a child of <Routes>", () => {
const CustomRoute = (...args: any) => <Route />;

expect(() => {
TestRenderer.create(
<MemoryRouter initialEntries={["/admin"]}>
<Routes>
<Route path="/" element={<h1>Home</h1>} />
<CustomRoute path="admin" element={<h1>Admin</h1>} />
</Routes>
</MemoryRouter>
);
}).toThrow(/children of <Routes> must be a <Route>/);

expect(consoleError).toHaveBeenCalledTimes(1);
});

it("throws if a regular element (ex: <div>) is passed as a child of <Routes>", () => {
expect(() => {
TestRenderer.create(
<MemoryRouter initialEntries={["/admin"]}>
<Routes>
<Route path="/" element={<h1>Home</h1>} />
<div {...({ path: "admin", element: <h1>Admin</h1> } as any)} />
</Routes>
</MemoryRouter>
);
}).toThrow(/children of <Routes> must be a <Route>/);

expect(consoleError).toHaveBeenCalledTimes(1);
});
});
7 changes: 7 additions & 0 deletions packages/react-router/index.tsx
Expand Up @@ -704,6 +704,13 @@ export function createRoutesFromChildren(
return;
}

invariant(
element.type === Route,
`[${
typeof element.type === "string" ? element.type : element.type.name
mjackson marked this conversation as resolved.
Show resolved Hide resolved
}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`
mjackson marked this conversation as resolved.
Show resolved Hide resolved
);

let route: RouteObject = {
caseSensitive: element.props.caseSensitive,
element: element.props.element,
Expand Down