网站搜索

javascript - 将自定义 Props 传递给私有路由 - React Typescript


我们有一个 React 组件 XYZ,它有某些需要根据挂载该组件的路由来隐藏或显示的 UI。

例如,如果路由是 /show -> 它将显示一个表格;如果路由是 /hide -> 它将隐藏该表格。

正在使用 react-router-dom,但不想在 history.push(...) 中使用 state。

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

附注:我们正在使用带有 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 中传递 props 然后再传递给 Component 的帮助都会不胜感激。提前感谢。

答案#1

道具

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

我们将把 type PrivateRouteProps 定义为一个依赖于 ExtraProps 类型的泛型。它将把额外传递的属性作为一个名为 extraProps 的对象接收。

我们的 PrivateRouteProps 将接受所有普通的 RouteProps,除了 component,因为我们想用自己的定义来覆盖它。我们的 component 版本是一个接收典型的 RouteComponentProps 以及我们的 ExtraProps(作为顶级属性)的组件。

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

组件

在我们的render函数中,我们可以通过检查props.match.path的值来实现show/hide切换,该值已经作为RouteComponentProps的一部分提供。

当我们调用 Component 时,我们会传递所有提供给 render 的 props,以及我们传递给 PrivateComponent 的所有 extraProps。我们根本不需要重写 render 的定义,我们只是将自己的额外 props 添加到已有的 props 上。如果不这样做,我们会出现错误,因为我们在类型上规定 Component 期望接收 ExtraProps。

我们的 PrivateRoute 是通用的,所以我们不会将组件本身类型化为 FunctionComponent,而是会对其 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 } }} />}
        />
    )
}

使用

现在当我们声明一个 PrivateRoute 时,我们必须始终传递适当的额外属性。

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

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

TypeScript 游乐场链接