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 游乐场链接
