8 typescript reactjs react-router react-router-dom
为了不重建从类组件到功能组件的所有内容,我需要使用 React Router文档中的包装器:
import {
useLocation,
useNavigate,
useParams,
} from "react-router-dom";
function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
Run Code Online (Sandbox Code Playgroud)
但是我需要更正Typescript 中Component的类型props。(任何快速测试都表明它有效)。但我需要使用哪些正确的类型?
这是我尝试过的,给出Component类型Function,但仍然不确定道具,因为我想避免使用任何..
import { useLocation, useNavigate, useParams } from "react-router-dom";
type IComponentWithRouterProp = {
[x: string]: any;
};
function withRouter(Component: Function) {
function ComponentWithRouterProp(props: IComponentWithRouterProp) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return <Component {...props} router={{ location, navigate, params }} />;
}
return ComponentWithRouterProp;
}
export default withRouter;
Run Code Online (Sandbox Code Playgroud)
编辑:
所以我发现我正在寻找的是React.ComponentType,它是 ComponentClass 和 ComponentFunction 的联合。
但是当我使用Component: React.ComponentType时,TS 在返回时在我的路由器上抛出错误 -router={{ location, navigate, params }}
Type '{ router: { location: Location; navigate: NavigateFunction; params: Readonly<Params<string>>; }; }' is not assignable to type 'IntrinsicAttributes'.
Property 'router' does not exist on type 'IntrinsicAttributes'.
Run Code Online (Sandbox Code Playgroud)
所以这会引发一个新的错误,我该如何解决这个问题?
ghy*_*ybs -1
确实有一些关于输入常见问题解答建议withRouter实现的博客,例如https://whereisthemouse.com/how-to-use-withrouter-hoc-in-react-router-v6-with-typescript
但看起来它使用的是以前版本的常见问题解答,其中location,params和navigateprops 直接内联为 props 键,而新的常见问题解答将它们收集在一个router字典中。这完全取决于您的类组件期望如何接收这些道具。
既然您说忽略类型问题(通常与any)在您的项目中有效,那么它就符合这种形式。因此,让我们调整一下输入:
import { useLocation, useNavigate, useParams } from "react-router-dom";
export interface WithRouterProps {
location: ReturnType<typeof useLocation>;
params: Record<string, string>;
navigate: ReturnType<typeof useNavigate>;
}
function withRouter<CProps extends { router: WithRouterProps }>(Component: React.ComponentType<CProps>) {
function ComponentWithRouterProp(props: Omit<CProps, "router">) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return <Component {...(props as CProps)} router={{ location, navigate, params }} />;
}
return ComponentWithRouterProp;
}
export default withRouter;
Run Code Online (Sandbox Code Playgroud)
我们来尝试一下:
class Welcome extends React.Component<{ name: string; router: WithRouterProps }> {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
// Bare component expects name and router props
<>
<Welcome name="Foo" /> {/* Error: Property 'router' is missing in type '{ name: string; }' but required in type 'Readonly<{ name: string; router: WithRouterProps; }>'.(2769)*/}
<Welcome name="Foo" router={({} as WithRouterProps)} />
</>
const WelcomeWithRouter = withRouter(Welcome);
// withRouter'ed component expects only name, router will be automatically provided
<>
<WelcomeWithRouter name="Foo" />
<WelcomeWithRouter name="Foo" router={({} as WithRouterProps)} /> {/* Error: Property 'router' does not exist on type 'IntrinsicAttributes & Omit<{ name: string; router: WithRouterProps; }, "router">'.(2322) */}
</>
Run Code Online (Sandbox Code Playgroud)
看起来不错!
| 归档时间: |
|
| 查看次数: |
2093 次 |
| 最近记录: |