typescript - 反应路线渲染属性类型挑战打字稿
问题描述
我有一些组件道具project
通过 a 传递Link
给Route
这样的(我的项目对象进入state
扩展属性):
<Link
to={{
pathname: path,
state: {
project,
},
}}
key={project.id}
>
<ProjectSummary project={project} deleteCallback={projectDelete}/>
</Link>
然后它在路由中接收并可以像这样传递给链接的组件:
<Route
path='/project/:id'
render={({ location }:any) => { //TYPE CHALLENGE HERE
const { state } = location;
return <ProjectDetails project={state.project} />
}}
/>
找到any
带有//TYPE CHALLENGE HERE
注释的类型。我尝试了很多类型的 'react-router' 和 'react-router-dom' 并且无法找到匹配的类型。
最接近的似乎是这个:
export interface RouteComponentProps<
Params extends { [K in keyof Params]?: string } = {},
C extends StaticContext = StaticContext,
S = H.LocationState
> {
history: H.History<S>;
location: H.Location<S>;
match: match<Params>;
staticContext?: C;
}
由于组件从该接口接收所有路由参数,但我扩展了location
传入我的项目对象的位置。如果它有任何相关性,这是project
我传入的对象的类型:
export interface IFirebaseProject {
id: string,
authorFirstName: string,
authorId: string,
authorLastName: string
content: string
createdAt: firebase.firestore.Timestamp //firebase timestamp
title: string
}
我还发布了我认为最接近的方法的错误:
render={({ location }:RouteComponentProps<any, StaticContext, IFirebaseProject>) => {}
No overload matches this call.
Overload 1 of 2, '(props: RouteProps | Readonly<RouteProps>): Route<RouteProps>', gave the following error.
Type '({ location }: RouteComponentProps<any, StaticContext, IFirebaseProject>) => JSX.Element' is not assignable to type '(props: RouteComponentProps<any, StaticContext, unknown>) => ReactNode'.
Types of parameters '__0' and 'props' are incompatible.
Type 'RouteComponentProps<any, StaticContext, unknown>' is not assignable to type 'RouteComponentProps<any, StaticContext, IFirebaseProject>'.
Type 'unknown' is not assignable to type 'IFirebaseProject'.
Overload 2 of 2, '(props: RouteProps, context: any): Route<RouteProps>', gave the following error.
Type '({ location }: RouteComponentProps<any, StaticContext, IFirebaseProject>) => JSX.Element' is not assignable to type '(props: RouteComponentProps<any, StaticContext, unknown>) => ReactNode'.ts(2769)
index.d.ts(89, 5): The expected type comes from property 'render' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Route<RouteProps>> & Readonly<RouteProps> & Readonly<...>'
index.d.ts(89, 5): The expected type comes from property 'render' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Route<RouteProps>> & Readonly<RouteProps> & Readonly<...>'
编辑:
render={({ location }: { location: Location<{ project: IFirebaseProject }> }) => {
尝试的错误的文本全文:
No overload matches this call.
Overload 1 of 2, '(props: RouteProps | Readonly<RouteProps>): Route<RouteProps>', gave the following error.
Type '({ location }: { location: Location<{ project: IFirebaseProject;}>; }) => JSX.Element' is not assignable to type '(props: RouteComponentProps<any, StaticContext, unknown>) => ReactNode'.
Types of parameters '__0' and 'props' are incompatible.
Type 'RouteComponentProps<any, StaticContext, unknown>' is not assignable to type '{ location: Location<{ project: IFirebaseProject; }>; }'.
Types of property 'location' are incompatible.
Type 'Location<unknown>' is not assignable to type 'Location<{ project: IFirebaseProject; }>'.
Type 'unknown' is not assignable to type '{ project: IFirebaseProject; }'.
Overload 2 of 2, '(props: RouteProps, context: any): Route<RouteProps>', gave the following error.
Type '({ location }: { location: Location<{ project: IFirebaseProject;}>; }) => JSX.Element' is not assignable to type '(props: RouteComponentProps<any, StaticContext, unknown>) => ReactNode'.ts(2769)
index.d.ts(89, 5): The expected type comes from property 'render' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Route<RouteProps>> & Readonly<RouteProps> & Readonly<...>'
index.d.ts(89, 5): The expected type comes from property 'render' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Route<RouteProps>> & Readonly<RouteProps> & Readonly<...>'
解决方案
RouteComponentProps
你是如此接近!S
参数RouteComponentProps
控制 the和props的state
类型,所以这就是你想要使用的。location
history
错误是您正在设置S
这IFirebaseProject
意味着状态本身就是一个IFirebaseProject
. 但现实中的状态是这样的{project}
。它是一个project
具有值为 的键的对象IFirebaseProject
。所以正确的类型S
是{project: IFirebaseProject}
.
正确设置所有类型后,它是这样的:
render={({ location }: RouteComponentProps<{id: string}, StaticContext, {project: IFirebaseProject}>) => {
但location
不使用其他两个泛型,所以这很好:
render={({ location }: RouteComponentProps<any, any, {project: IFirebaseProject}>) => {
地点
就我个人而言,我只会为该属性声明一个类型,因为这是您实际需要location
的唯一属性。RouteComponentProps
我不喜欢使用依赖于未使用的泛型的类型。
底层Location
类型来自历史包,它是 react-router 的依赖项。它的类型被导入到 react-router-dom 类型中import * as H from "history"
,所以这就是你看到H.Location
. 但是你可以直接导入它:
import {Location} from "history";
并像这样使用它:
render={({ location }: {location: Location<{project: IFirebaseProject}>}) => {
编辑:render
对。component
您的 CodeSandbox 中发生了一些奇怪的事情,因为我确实看到了错误,但我无法在 TS Playground 中单独重现它。与其把我们的头撞到墙上,不如使用一种稍微不同的方法来规避错误。
props的component
类型比render
它允许的 props 类型要宽松得多,因为它允许 props 类型是RouteComponentProps<any>
(我们期望的)或any
(字面上的任何东西)。只需将道具名称从 切换render
到component
,它就会突然起作用!我们不想内联定义组件,因为它将在每次渲染时重新创建,但我们可以在外部定义它。
我们现在将使用component
propRoute
代替render
函数:
<Route path="/project/:id" component={ProjectScreen} />
有两个选项可以访问ProjectScreen
似乎都对我有用的位置。
- 我们可以通过组件中注入的 props 来访问它。这正是我们之前所拥有的,但它是允许的,
component
而不是render
由于any
道具上的类型。
const ProjectScreen = ({ location }: { location: Location<{ project: IFirebaseProject }>; }) => {
const { state } = location;
return <ProjectDetails project={state.project} />;
};
useLocation
我们可以使用钩子通过路由器上下文访问它。这个钩子根据状态是通用的,所以我们可以在调用它的时候指定状态类型。我们定义了一个组件,它不接受任何道具,但会ProjectDetails
根据钩子的位置呈现适当的。
const ProjectScreen = () => {
const { state } = useLocation<{ project: IFirebaseProject }>();
return <ProjectDetails project={state.project} />;
}
推荐阅读
- linux - linux shell重定向命令的顺序
- elixir - 按插入顺序从 mnesia 中检索数据
- python - 替换每行第一个单词中所有匹配正则表达式的匹配项
- python - Python 语法 - 连续对一个变量执行多个函数
- mysql - 在macOS中快速连接到mysql
- here-api - iOS - 动作使用权限
- c - 使用高斯算法计算星期几
- spring - 每个目标套接字的 RestTemplate(或 WebClient)和连接超时
- django - ImportError:尽管安装了运行 apache2 服务器的模块,但没有名为“django”的模块
- javascript - 将异步函数的值设置为 .then 的返回值