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