Here is an example from react-router for how to add a component for protected routes:
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
}
https://reacttraining.com/react-router/web/example/auth-workflow
I have tried to implement this functionality in my Typescript project, using the example above as inspiration.
components/Routes
import PrivateRoute from '../../connectors/PrivateRoute';
<PrivateRoute path="/codes" component={SomePage} />
connectors/PrivateRoute
import { connect } from 'react-redux';
import { AppState } from 'app-types';
import PrivateRouteComponent from '../../components/PrivateRoute';
const mapStateToProps = (state: AppState) => {
const isSignedIn = state.user.isSignedIn;
return {
isSignedIn
};
};
const PrivateRoute = connect(
mapStateToProps,
null
)(PrivateRouteComponent);
export default PrivateRoute;
components/PrivateRoute
import * as React from 'react';
import {
Route,
Redirect,
} from 'react-router-dom';
interface PrivateRouteProps {
// tslint:disable-next-line:no-any
component: any;
isSignedIn: boolean;
// tslint:disable-next-line:no-any
location: any;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, isSignedIn, location, ...rest } = props;
return (
<Route
{...rest}
render={(routeProps) =>
isSignedIn ? (
<Component {...routeProps} />
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: location }
}}
/>
)
}
/>
);
};
export default PrivateRoute;
Error
(105,18): Type '{ path: string; component: ConnectedComponentClass<typeof SomePage, Pick<SomePageProps, never>>; }' is not assignable to type 'Readonly<Pick<PrivateRouteProps, "location" | "component">>'.
Property 'location' is missing in type '{ path: string; component: ConnectedComponentClass<typeof SomePage, Pick<SomePageProps, never>>; }'.
To install React Router, all you have to do is run npm install react-router-dom@6 in your project terminal and then wait for the installation to complete. If you are using yarn then use this command: yarn add react-router-dom@6 .
The error occurs because PrivateRouteProps
has a required property location
that isn't provided when you use PrivateRoute
in components/Routes.tsx
. I assume that this location should instead come from the routeProps
that the router automatically passes to the render
function of the route, as it did in the original example. Once this is fixed, another error is exposed: components/Routes.tsx
is passing a paths
property that isn't declared in PrivateRouteProps
. Since PrivateRoute
is passing any prop it doesn't know about to Route
, PrivateRouteProps
should extend RouteProps
from react-router
so that PrivateRoute
accepts all props accepted by Route
.
Here is components/PrivateRoute.tsx
after both fixes:
import * as React from 'react';
import {
Route,
Redirect,
RouteProps,
} from 'react-router-dom';
interface PrivateRouteProps extends RouteProps {
// tslint:disable-next-line:no-any
component: any;
isSignedIn: boolean;
}
const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, isSignedIn, ...rest } = props;
return (
<Route
{...rest}
render={(routeProps) =>
isSignedIn ? (
<Component {...routeProps} />
) : (
<Redirect
to={{
pathname: '/signin',
state: { from: routeProps.location }
}}
/>
)
}
/>
);
};
export default PrivateRoute;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With