将自定义道具传递到专用路线-反应打字稿

时间:2020-06-28 13:56:47

标签: javascript reactjs typescript react-router react-router-dom

我们有一个React组件XYZ,其中某些UI需要根据已安装该组件的路由进行隐藏/显示。

例如,如果路由为/ show->,则应显示一个表 如果路线是/ hide->,它将隐藏表格。

正在使用react-router-dom,但不希望在history.push(...)中使用状态。

我正在寻找可以在定义路由时实现的解决方案,以便以后使用此路由的任何开发人员都不必担心保持状态。

PS:我们在TS中使用了专用路由,除非使用any,否则无法覆盖render方法。

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 } }} />}
        />
    )
}

用法:

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

任何有关如何在此PrivateRoute中传递道具然后将其传递到组件的帮助都将受到赞赏。TIA

1 个答案:

答案 0 :(得分:0)

道具

我假设这些额外的道具是已知的,并且可以作为道具传递给PrivateRoute组件。

我们将type PrivateRouteProps定义为泛型,这取决于ExtraProps的类型。

它将以道具名称为extraProps的对象作为附加对象。

我们的PrivateRouteProps将接受除RouteProps以外的所有常规component,因为我们想用我们自己的定义覆盖它。我们的component版本既包含典型的RouteComponentProps,也包含我们的ExtraProps(作为顶级道具)。

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

组件

在我们的render函数中,我们可以通过检查show的值来实现hide / props.match.path的切换,RouteComponentProps的值已经提供了{{1} }。

当我们调用Component时,我们会传递给render的所有道具以及传递给extraProps的所有PrivateComponent 。我们根本不必覆盖render的定义,我们只是在给出的内容之上添加了自己的额外道具。如果不这样做,则会因为输入Component使其期望收到ExtraProps而出错。

我们的PrivateRoute是通用的,因此我们将输入道具而不是将组件本身键入为FunctionComponent

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 } }} />}
        />
    )
}

用法

现在,当我们声明PrivateRoute时,我们必须始终传递适当的额外道具。

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

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

Typescript Playground Link