Skip to content

Commit cdea2a2

Browse files
Ensure react-router tests don't fail (#511)
* Ensure react-router tests don't fail * Add comments; centralize more types * Last little bit of type patching * don't need to override RouteMatch because we live in magic town Co-authored-by: David Crespo <[email protected]>
1 parent 41cca06 commit cdea2a2

File tree

4 files changed

+26
-33
lines changed

4 files changed

+26
-33
lines changed

app/components/Breadcrumbs.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import React from 'react'
22

33
import type { Crumb } from '@oxide/ui'
44
import { Breadcrumbs as BreadcrumbsPure } from '@oxide/ui'
5-
import type { CustomMatch } from '../hooks/use-matches'
65
import { useMatches } from '../hooks/use-matches'
6+
import type { RouteMatch } from 'react-router'
77

8-
export function matchesToCrumbs(matches: CustomMatch[]): Crumb[] {
8+
export function matchesToCrumbs(matches: RouteMatch[]): Crumb[] {
99
const filtered = matches.filter((m) => m.route.crumb)
1010
return filtered.map((m, i) => ({
1111
label:

app/hooks/use-matches.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import type { RouteMatch } from 'react-router'
22
import { matchRoutes, useLocation } from 'react-router'
33

4-
import type { CustomRouteObject } from '../routes'
54
import { routeConfig } from '../routes'
65

7-
export type CustomMatch = RouteMatch & {
8-
route: CustomRouteObject
9-
}
10-
116
/**
127
* For the current location, return the path down the route config. For example,
138
* if the route config is
@@ -30,5 +25,5 @@ export type CustomMatch = RouteMatch & {
3025
* ]
3126
* ```
3227
*/
33-
export const useMatches = (): CustomMatch[] | null =>
28+
export const useMatches = (): RouteMatch[] | null =>
3429
matchRoutes(routeConfig, useLocation())

app/routes.tsx

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import React from 'react'
22

3-
import type {
4-
RouteMatch,
5-
RouteObject,
6-
RouteProps as RRRouteProps,
7-
} from 'react-router'
8-
import { Navigate, Route as RRRoute, Routes } from 'react-router-dom'
3+
import type { RouteMatch, RouteObject } from 'react-router'
4+
import { Navigate, Route, Routes } from 'react-router-dom'
95

106
import InstanceCreatePage from './pages/instances/create'
117
import InstanceStorage from './pages/instances/Storage'
@@ -22,20 +18,6 @@ import OrgLayout from './layouts/OrgLayout'
2218
import ProjectLayout from './layouts/ProjectLayout'
2319
import InstanceLayout from './layouts/InstanceLayout'
2420

25-
// function arm lets us make labels that depend on route params
26-
type Crumb = string | ((m: RouteMatch) => string)
27-
28-
type RouteProps = RRRouteProps & {
29-
crumb?: Crumb
30-
}
31-
32-
export type CustomRouteObject = RouteObject & {
33-
crumb?: Crumb
34-
}
35-
36-
/** Custom `<Route>` that accepts whatever props we want. */
37-
const Route = (props: RouteProps) => <RRRoute {...props} />
38-
3921
/*
4022
* We are doing something a little unorthodox with the route config here. We
4123
* realized that tagging nodes in the route tree with arbitrary data is very
@@ -49,6 +31,9 @@ const Route = (props: RouteProps) => <RRRoute {...props} />
4931
* The config ends up being a bit more complicated that it would otherwise be
5032
* because, e.g., we have to do `orgs` and `:orgName` separately in order to get
5133
* a crumb for each; `orgs/:orgName` would otherwise be ok.
34+
*
35+
* Note that `crumb` is defined via patched react-router types in
36+
* `types/react-router.d.ts`
5237
*/
5338

5439
/* eslint-disable @typescript-eslint/no-non-null-assertion */
@@ -155,10 +140,8 @@ export const routes = (
155140
* in order to be able to put `crumb` prop directly on the <Route> elements
156141
* https://github.com/remix-run/react-router/blob/174fb105ee/packages/react-router/index.tsx#L685
157142
* */
158-
function createRoutesFromChildren(
159-
children: React.ReactNode
160-
): CustomRouteObject[] {
161-
const routes: CustomRouteObject[] = []
143+
function createRoutesFromChildren(children: React.ReactNode): RouteObject[] {
144+
const routes: RouteObject[] = []
162145

163146
React.Children.forEach(children, (element) => {
164147
if (!React.isValidElement(element)) {
@@ -174,7 +157,7 @@ function createRoutesFromChildren(
174157
}
175158

176159
// only real difference from the original: allow arbitrary props
177-
const route: CustomRouteObject = { ...element.props }
160+
const route: RouteObject = { ...element.props }
178161

179162
if (element.props.children) {
180163
route.children = createRoutesFromChildren(element.props.children)

types/react-router.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type {
2+
RouteProps as OriginalRouteProps,
3+
RouteObject as OriginalRouteObject,
4+
} from 'react-router'
5+
6+
declare module 'react-router' {
7+
type Crumb = string | ((m: RouteMatch) => string)
8+
export interface RouteProps extends OriginalRouteProps {
9+
crumb?: Crumb
10+
}
11+
export interface RouteObject extends OriginalRouteObject {
12+
crumb?: Crumb
13+
}
14+
export function Route(props: RouteProps): React.ReactElement | null
15+
}

0 commit comments

Comments
 (0)