reactjs - Implementere react-router PrivateRoute i Typescript-prosjekt


Her er et eksempel fra react-router på hvordan man legger til en komponent for beskyttede ruter:

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

Jeg har prøvd å implementere denne funksjonaliteten i mitt Typescript-prosjekt, ved å bruke eksemplet ovenfor som inspirasjon.

komponenter/Ruter

import PrivateRoute from '../../connectors/PrivateRoute';
<PrivateRoute path="/codes" component={SomePage} />

kontakter/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;

komponenter/PrivatRute

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;

Feil

(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>>; }'.

Svar #1

Feilen oppstår fordi PrivateRouteProps har en obligatorisk egenskap location som ikke er gitt når du bruker PrivateRoute i components/Routes.tsx. Jeg antar at denne location i stedet bør komme fra routeProps som ruteren automatisk sender til render-funksjonen til ruten, slik det ble gjort i det opprinnelige eksemplet. Når dette er fikset, blir en annen feil synlig: components/Routes.tsx sender en paths-egenskap som ikke er deklarert i PrivateRouteProps. Siden PrivateRoute sender videre alle egenskaper den ikke kjenner til Route, bør PrivateRouteProps utvide RouteProps fra react-router slik at PrivateRoute aksepterer alle egenskaper som Route aksepterer.

Her er components/PrivateRoute.tsx etter begge rettelsene:

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;

Relaterte artikler