简体   繁体   中英

Pass custom Props to Private Route - React Typescript

We have a React component XYZ that has certain UI that needs to be hidden/showed based on the route that has mounted the component.

For eg, if the route is /show -> it shall show a table if the route is /hide-> it shall hide the table.

react-router-dom is being used, but would not like to use state in history.push(...).

Am looking for a solution that can be achieved while defining the routes so that any developer who used this route later don't have to worry about maintaining the state.

PS: We are using Private Route with TS, and overriding the render method is not possible unless any is used.

interface PrivateRouteProps extends RouteProps {
}

const PrivateRoute: FunctionComponent<PrivateRouteProps> = ({
    component: Component,
    ...rest
  }) => {
    if (!Component) return null;    
    return (
        <Route
            {...rest}
            render={(props) => true
                ? <Component {...props}/>  // looking for a way to pass custom props here
                : <Redirect to={{ pathname: '/', state: { from: props.location } }} />}
        />
    )
}

usage:

<PrivateRoute path='/show' component={XYZ} />

Any help on how can I pass props in this PrivateRoute and then pass it on to the Component will be appreciated.TIA

Props

I am assuming that that the extra props are known and can be passed as props to the PrivateRoute component.

We will define the type PrivateRouteProps as a generic which depends on the type of ExtraProps . It will take the additional passed-down props as an object with the prop name extraProps .

Our PrivateRouteProps will accept all of the normal RouteProps except for component , because we want to override that with our own definition. Our version of the component is one which takes the typical RouteComponentProps and also our ExtraProps (as top-level props).

type PrivateRouteProps<ExtraProps> = Omit<RouteProps, 'component'> & {
  component: ComponentType<RouteComponentProps & ExtraProps>
  extraProps: ExtraProps;
}

Component

In our render function, we can implement the show / hide toggling by checking the value of props.match.path , which is already provided a part of RouteComponentProps .

When we call the Component , we pass down all of the props which were provided to the render and also all of the extraProps that we passed in to PrivateComponent . We are not having to overwrite the definition of render at all, we're just adding our own extra props on top of what's given. If we didn't, we would get errors because we typed the Component such that it expects to receive ExtraProps .

Our PrivateRoute is generic, so instead of typing the component itself as FunctionComponent , we will type the props.

const PrivateRoute = <ExtraProps extends {}>({
    component: Component,
    extraProps,
    ...rest
  }: PrivateRouteProps<ExtraProps>) => {
    if (!Component) return null;
    return (
        <Route
            {...rest}
            render={(props) => props.match.path.startsWith('/show')
                ? <Component {...extraProps} {...props}/>
                : <Redirect to={{ pathname: '/', state: { from: props.location } }} />}
        />
    )
}

Usage

Now when we declare a PrivateRoute , we must always pass the appropriate extra props.

const RenderNumber = ({n}: {n: number}) => (
  <div>{n}</div>
)

<PrivateRoute path="/show/something" component={RenderNumber} extraProps={{n: 5}}/>
// renders the number 5

Typescript Playground Link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM