Skip to content

Commit

Permalink
feat: migrate to use react-router-dom@6
Browse files Browse the repository at this point in the history
  • Loading branch information
DevNico committed Nov 9, 2021
1 parent 6451b77 commit 172c5cf
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 164 deletions.
11 changes: 8 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@

## 1.0.0 (unreleased)

Features:
BREAKING:

- BREAKING: upgrade to use `react-router-dom: ^6.0.1`
- BREAKING: `Redirect` renamed to `Navigate` to conform with react-router-dom naming
- upgrade to use `react-router-dom: ^6.0.1`
- `Redirect` renamed to `Navigate` to conform with react-router-dom naming
- `RouterSwitch` renamed to `RouterRoutes` to conform with react-router-dom naming
- the `sensitive` prop of a route was renamed to `caseSensitive` to conform with react-router-dom naming
- the `strict` prop of a route does no longer exist
- the `exact` prop of a route does no longer exist. If you need your path to be deep matching add a `*` to the end
- the `component` prop of the route function now requires a `React.ReactComponent` instead of a `React.ReactElement`.

Fix:

Expand Down
59 changes: 28 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The last routing library you will ever need in your React projects. (At least if
- [useRouteParams](#userouteparams)
- [useRouteActive and useRoutesActive](#userouteactive-and-useroutesactive)
- [Components](#components)
- [RouterSwitch](#routerswitch)
- [RouterRoutes](#routerroutes)
- [Link](#link)
- [NavLink](#navlink)
- [Navigate](#navigate)
Expand Down Expand Up @@ -75,35 +75,35 @@ const AuthMiddleware: RouteMiddleware = (next) => {

export const router = OptionsRouter(defaultOptions, route => ({
home: route('/', {
component: HomePage,
component: <HomePage />
}),
login: route('/login', {
component: LoginPage,
component: <LoginPage />
options: { appBar: false },
}),
players: route(
'/players',
{
component: PlayersPage,
component: <PlayersPage />
middleware: AuthMiddleware,
},
route => ({
info: route(
'/:name/:id',
{
component: PlayerInfoPage,
component: <PlayerInfoPage />
params: {
name: stringParser,
id: intParser,
},
},
route => ({
rating: route('/rating/:id', {
component: PlayerRatingPage,
component: <PlayerRatingPage />
params: { id: intParser },
}),
ban: route('/rating/:id', {
component: PlayerRatingPage,
component: <PlayerRatingPage />
params: { id: intParser },
}),
})
Expand Down Expand Up @@ -136,7 +136,7 @@ const App = () => {
<BrowserRouter>
<div>
{ appBar && <AppBar />}
<RouterSwitch router={router} />
<RouterRoutes router={router} />
</div>
</BrowserRouter>
);
Expand Down Expand Up @@ -164,10 +164,10 @@ const defaultOptions = {

const router = OptionsRouter(defaultOptions, route => ({
home: route('/', {
component: HomePage,
component: <HomePage />
}),
login: route('/login', {
component: LoginPage,
component: <LoginPage />
options: { appBar: false }
}),
});
Expand All @@ -178,7 +178,7 @@ const App = () => {
return (
<div>
{options.appBar && <AppBar>}
<RouterSwitch router={router} />
<RouterRoutes router={router} />
</div>
);
};
Expand All @@ -190,17 +190,17 @@ The Router is basically the same as the OptionsRouter but it doesn't have Option
```tsx
const router = Router(route => ({
home: route('/', {
component: HomePage,
component: <HomePage />
}),
login: route('/login', {
component: LoginPage,
component: <LoginPage />
}),
});

const App = () => {
return (
<div>
<RouterSwitch router={router} />
<RouterRoutes router={router} />
</div>
);
};
Expand Down Expand Up @@ -230,11 +230,8 @@ const router = OptionsRouter(options, route => ({
// Global options for this route
options?: Partial<RO>;

// Wether or not to include this routes child routes in a RouterSwitch - Defaults to true
// Wether or not to include this routes child routes in a RouterRoutes - Defaults to true
includeChildren?: boolean;

// Wether or not this route is exact - Defaults to true
exact?: boolean;
}
),
});
Expand All @@ -249,7 +246,7 @@ Basic parameters are defined with a colon in front of them.
```tsx
const router = Route(route => ({
test: route('test/:id', {
component: TestPage,
component: <TestPage />,
params: {
id: intParser,
}
Expand All @@ -264,7 +261,7 @@ If you want a parameter to be optional you can add a question mark behind it. Op
```tsx
const router = Route(route => ({
test: route('test/:id?', {
component: TestPage,
component: <TestPage />,
params: {
id: intParser,
}
Expand All @@ -279,7 +276,7 @@ A query parameter has an ampersand in front of it, they can be chained and also
```tsx
const router = Route(route => ({
test: route('test/:id?&:filter&:page?', {
component: TestPage,
component: <TestPage />,
params: {
id: intParser,
page: intParser,
Expand All @@ -296,7 +293,7 @@ Child routes can be defined with the third argument of the route function - Anot
```tsx
const router = Route(route => ({
test: route('test/:id?&:filter&:page?', {
component: TestPage,
component: <TestPage />,
params: {
id: intParser,
page: intParser,
Expand Down Expand Up @@ -328,10 +325,10 @@ const AuthMiddleware: RouteMiddleware = (next) => {

export const router = Router(route => ({
login: route('login', {
component: Login,
component: <Login />,
}),
restricted: route('restricted', {
component: Restricted,
component: <Restricted />,
middleware: AuthMiddleware,
}),
});
Expand All @@ -357,7 +354,7 @@ const testTabs = ['overview', 'statistics', 'comments'] as const;

const router = Route(route => ({
test: route('test&:tab', {
component: TestPage,
component: <TestPage />,
params: {
tab: stringListParser(testTabs),
}
Expand Down Expand Up @@ -398,10 +395,10 @@ This is useful whenever you need those global route options of an [OptionsRouter
const options = { appBar: true };
const router = OptionsRouter(options, route => ({
home: route('', {
component: HomePage
}),
component: <HomePage />
}),
entry: route('entries/:id', {
component: EntryPage
component: <EntryPage />
params: {
id: intParser
}
Expand Down Expand Up @@ -476,12 +473,12 @@ export const App = () => {

## Components

### RouterSwitch
### RouterRoutes

This is what you would use instead of the `Switch` and `Route` from `react-router-dom`. You just give it your router and it automatically adds al the routes for you.
This is what you would use instead of the `Routes` and `Route` from `react-router-dom`. You just give it your router and it automatically adds al the routes for you.

```tsx
<RouterSwitch router={router}/>
<RouterRoutes router={router}/>
```

### Link
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@
"path": "dist/react-typesafe-routes.esm.js",
"limit": "10 KB"
}
]
],
"dependencies": {}
}
6 changes: 2 additions & 4 deletions src/components/Route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ export const Route = (
) => (
<OriginalRoute
{...p}
path={p.to?.fullTemplate ?? p.path}
strict={p.to?.strict ?? p.strict ?? false}
exact={p.to?.exact ?? p.exact ?? false}
sensitive={p.to?.sensitive ?? p.sensitive ?? false}
path={p.to?.fullTemplate ?? p.path!}
caseSensitive={p.to?.caseSensitive ?? p.caseSensitive ?? false}
/>
);
22 changes: 10 additions & 12 deletions src/components/RouterSwitch.tsx → src/components/RouterRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
import * as React from 'react';
import { Route, Switch } from 'react-router-dom';
import { Route, Routes } from 'react-router-dom';
import { AnyRouterType } from '../router';
import { anyRouterToRouteList } from '../utils/routerUtils';

/**
* Props for a RouterSwitch
* Props for a RouterRoutes component
*/
interface RouterSwitchProps {
interface RouterRoutesProps {
router: AnyRouterType;
}

/**
* react-router-dom Switch wrapper that creates Route components for every route defined in the given router
* react-router-dom Routes wrapper that creates Route components for every route defined in the given router
*
* @param props - Props containing the router to use
*/
export const RouterSwitch = (props: RouterSwitchProps) => {
export const RouterRoutes = (props: RouterRoutesProps) => {
return (
<Switch>
<Routes>
{anyRouterToRouteList(props.router).map((route, index) => {
const Component = route.render();
const Element = route.render();
return (
<Route
key={index}
path={route.fullTemplate}
exact={route.exact}
strict={route.strict}
sensitive={route.sensitive}
component={Component}
caseSensitive={route.caseSensitive}
element={Element}
/>
);
})}
</Switch>
</Routes>
);
};
2 changes: 1 addition & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export * from './NavLink';
export * from './Link';
export * from './Navigate';
export * from './Route';
export * from './RouterSwitch';
export * from './RouterRoutes';
16 changes: 2 additions & 14 deletions src/hooks/useRouteActive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,7 @@ import { AnyRouteNode } from '../routeNode';
*
* @returns true if the given `route` is active or false if not
*/
export const useRouteActive = (
route: AnyRouteNode,
options?: {
strict?: boolean;
exact?: boolean;
}
): boolean => {
export const useRouteActive = (route: AnyRouteNode): boolean => {
const { pathname } = useLocation();
return (
matchPath(pathname, {
path: route.fullTemplate,
strict: options?.strict ?? route.strict,
exact: options?.exact ?? route.exact,
}) != null
);
return matchPath(pathname, route.fullTemplate) != null;
};
5 changes: 1 addition & 4 deletions src/hooks/useRouteOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ export const useRouteOptions = <RO extends RouteOptions>(

const routeList = routerToRouteList<RO>(router, true);
const route = routeList.filter(
route =>
matchPath(pathname, {
path: route.fullTemplate,
}) != null
route => matchPath(pathname, route.fullTemplate) != null
);

return (route[0]?.options as RO) ?? router.defaultOptions;
Expand Down
13 changes: 2 additions & 11 deletions src/hooks/useRoutesActive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,13 @@ import { ChildRouteMap } from '../routeFn';
* for each indicating wether or not the route is active
*/
export const useRoutesActive = <CRM extends ChildRouteMap<any>>(
routes: CRM,
options?: {
strict?: boolean;
exact?: boolean;
}
routes: CRM
): { [K in keyof CRM]: boolean } => {
const { pathname } = useLocation();

return Object.entries(routes)
.map(v => ({
[v[0]]:
matchPath(pathname, {
path: v[1].fullTemplate,
strict: options?.strict ?? v[1].strict,
exact: options?.exact ?? v[1].exact,
}) != null,
[v[0]]: matchPath(pathname, v[1].fullTemplate) != null,
}))
.reduce((v, c) => Object.assign(v, c)) as any;
};
23 changes: 1 addition & 22 deletions src/routeArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,6 @@ type RouteFnBaseArgs<RO extends RouteOptions> = {
*/
includeChildren?: boolean;

/**
* When true, will only match if the path matches the location.pathname exactly.
*
* @remark
* Taken from https://reactrouter.com/web/api/Route/exact-bool
*
* @defaultValue true
*/
exact?: boolean;

/**
* When true, a path that has a trailing slash will only match a location.pathname
* with a trailing slash. This has no effect when there are additional URL segments in the location.pathname.
*
* @remark
* Taken from https://reactrouter.com/web/api/Route/strict-bool
*
* @defaultValue false
*/
strict?: boolean;

/**
* When true, will match if the path is case sensitive.
*
Expand All @@ -102,5 +81,5 @@ type RouteFnBaseArgs<RO extends RouteOptions> = {
*
* @defaultValue false
*/
sensitive?: boolean;
caseSensitive?: boolean;
};
Loading

0 comments on commit 172c5cf

Please sign in to comment.