Skip to content

Commit

Permalink
Add fallback for private routes, allow multiple elements in <Walls>
Browse files Browse the repository at this point in the history
  • Loading branch information
drublic committed Dec 19, 2020
1 parent e3c742d commit d1bb3c3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 36 deletions.
14 changes: 8 additions & 6 deletions src/PrivateRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import React, { FunctionComponent, ReactElement } from "react";
import { Route, withRouter } from "react-router-dom";
import React, { FunctionComponent } from "react";
import { Route } from "react-router-dom";

interface Props {
isAuthorized: boolean;
onUnauthorized: (props: any) => void;
onUnauthorized?: (props: any) => void;
fallback?: FunctionComponent<any>;
}

const PrivateRoute: FunctionComponent<Props> = ({
isAuthorized,
onUnauthorized,
fallback,
...props
}): ReactElement<any> | null => {
}) => {
if (!isAuthorized) {
if (typeof onUnauthorized === "function") {
onUnauthorized(props);
}

return null;
return <Route {...props}>{fallback}</Route>;
}

return <Route {...props} />;
};

export default withRouter(PrivateRoute as any);
export default PrivateRoute;
16 changes: 7 additions & 9 deletions src/Walls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,39 @@ export interface RouteProps {
exact?: boolean;
path?: string | string[];
render: (props: any) => ReactNode;
fallback?: FunctionComponent<any>;
}

interface Props {
routes: RouteProps[];
isAuthorized?: boolean;
onUnauthorized?: (props: any) => void;
children?: ReactElement<any>;
}

const Walls: FunctionComponent<Props> = ({
routes,
isAuthorized = false,
onUnauthorized,
children,
}): ReactElement<any> => {
const PrivateRouteAny = PrivateRoute as any;
}) => {
return (
<Router>
<>
{children}

<Switch>
{routes.map(
(route: RouteProps): ReactElement<any> => {
const { private: privateRoute, id, path, ...props } = route;
const key = `route-${
id || path || (Math.random() * 10000).toFixed(4)
}`;
(route: RouteProps, index: number): ReactElement<any> => {
const { private: privateRoute, id, fallback, ...props } = route;
const key = `route-${id || props.path || index}`;

if (privateRoute) {
return (
<PrivateRouteAny
<PrivateRoute
key={key}
isAuthorized={isAuthorized}
onUnauthorized={onUnauthorized}
fallback={fallback}
{...props}
/>
);
Expand Down
50 changes: 32 additions & 18 deletions src/__tests__/visual/Container.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
import React, { ReactElement } from "react";
import React, { FunctionComponent, ReactElement, useState } from "react";
import { NavLink } from "react-router-dom";

import Walls from "../../../index";

import routes from "./routes";

const Container = (): ReactElement<any> => (
<Walls routes={routes}>
<nav>
<ul>
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/foo">Foo</NavLink>
</li>
<li>
<NavLink to="/bar">Bar (Private)</NavLink>
</li>
</ul>
</nav>
</Walls>
);
const Container: FunctionComponent<any> = () => {
const [isAuthorized, setIsAuthorized] = useState(false);
return (
<Walls routes={routes} isAuthorized={isAuthorized}>
<div style={{ display: "flex" }}>
<nav>
<ul>
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/foo">Foo</NavLink>
</li>
<li>
<NavLink to="/bar">Bar (Private)</NavLink>
</li>
</ul>
</nav>

<div>
<label htmlFor="isAuthorized">Is Authorized?</label>
<input
type="checkbox"
onChange={() => setIsAuthorized(!isAuthorized)}
id="isAuthorized"
/>
</div>
</div>
</Walls>
);
};

export default Container;
7 changes: 4 additions & 3 deletions src/__tests__/visual/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ export default [
private: false,
exact: true,
path: "/",
render: (): ReactElement<any> => <p>Home</p>,
render: () => <p>Home</p>,
},
{
private: false,
exact: true,
path: "/foo",
render: (): ReactElement<any> => <p>Foo</p>,
render: () => <p>Foo</p>,
},
{
private: true,
exact: true,
path: "/bar",
render: (): ReactElement<any> => <p>Bar (Private)</p>,
render: () => <p>Bar (Private)</p>,
fallback: () => <p>Unauthorized</p>,
},
];

0 comments on commit d1bb3c3

Please sign in to comment.