如何向withRouter包装的React类组件传递Props?
类组件使用withRouter后Props传递的TypeScript错误
问题重现
有一个需要传递Props的类组件TestClass,定义如下:
type TestProps = { location: any setMill: (value: any) => void } class TestClass extends Component<TestProps> { componentDidMount() { this.setState({ userRoleRating: 5 }); } render() { return <></> } } export default withRouter(TestClass as any)
在函数组件Layout中调用该类组件并传递setMill属性:
type LayoutProps = { children?: React.ReactElement setMill: (value: any) => void } const Layout: React.FC<LayoutProps> = (props: LayoutProps) => { return <> <TestClass setMill={props.setMill}/> <Container className="root-wrapper">{props.children}</Container> <Footer /> </> } export default Layout
出现TypeScript错误:
Type '{ setMill: (value: any) => void; }' is not assignable to type 'IntrinsicAttributes & (IntrinsicClassAttributes<Component<Pick<RouteComponentProps<any, StaticContext, unknown>, never> | (Pick<RouteComponentProps<any, StaticContext, unknown>, never> & { ...; }), any, any>> & Readonly<...>)'. Property 'setMill' does not exist on type 'IntrinsicAttributes & (IntrinsicClassAttributes<Component<Pick<RouteComponentProps<any, StaticContext, unknown>, never> | (Pick<RouteComponentProps<any, StaticContext, unknown>, never> & { ...; }), any, any>> & Readonly<...>)'.ts(2322)
解决方案
问题确实出在withRouter的类型处理上,错误地用as any断言导致TypeScript丢失了组件的Props类型信息。正确的修复步骤如下:
1. 让TestProps继承RouteComponentProps
withRouter会自动注入路由相关Props(比如location),不需要手动在TestProps中声明,直接继承RouteComponentProps即可:
import { Component } from 'react'; import { RouteComponentProps, withRouter } from 'react-router-dom'; // 自定义Props + 路由注入的Props type TestProps = RouteComponentProps & { setMill: (value: any) => void }
2. 补充类组件的State类型定义
组件中使用了setState,需要明确State的类型:
class TestClass extends Component<TestProps, { userRoleRating: number }> { // 初始化state state = { userRoleRating: 0 }; componentDidMount() { this.setState({ userRoleRating: 5 }); } render() { return <></> } }
3. 正确导出组件,移除as any断言
直接用withRouter包裹组件,不需要类型断言,让TypeScript自动推导类型:
export default withRouter(TestClass);
4. 调用组件时正常传递Props
此时在Layout中传递setMill就不会有类型错误了,原Layout代码无需修改。
完整修改后的代码
// TestClass.tsx import { Component } from 'react'; import { RouteComponentProps, withRouter } from 'react-router-dom'; type TestProps = RouteComponentProps & { setMill: (value: any) => void } class TestClass extends Component<TestProps, { userRoleRating: number }> { state = { userRoleRating: 0 }; componentDidMount() { this.setState({ userRoleRating: 5 }); } render() { return <></> } } export default withRouter(TestClass);
// Layout.tsx import React from 'react'; import TestClass from './TestClass'; import { Container } from 'your-ui-library'; // 替换为实际的UI组件 import Footer from './Footer'; type LayoutProps = { children?: React.ReactElement setMill: (value: any) => void } const Layout: React.FC<LayoutProps> = (props: LayoutProps) => { return <> <TestClass setMill={props.setMill}/> <Container className="root-wrapper">{props.children}</Container> <Footer /> </> } export default Layout
内容的提问来源于stack exchange,提问作者Quribe
相关产品推荐
相关产品推荐

