发生背景
又是React Router DOM v6的坑。
有个路由是/news/:number
,路径参数要通过useParams
hook获取,而hook不支持在类组件中使用。
location.href
也得用useLocation
hook获取,否则提示未声明。
相关代码
/src/pages/news/index.tsx
(缩减版):
class NewsDetail extends React.Component {
state: NewsDetailState = {
news: {
id: "",
number: "", // number字段是string类型的
title: "name",
content: "",
element: <Spin />
}
}
constructor(props: NewsDetailProps) {
super(props);
let state = this.state;
state.news.number = useParams().id as string;
state.news.element = (<>
<Grid.Row justify='center'>
<Typography.Title heading={ 1 }>{ state.news.title }</Typography.Title>
</Grid.Row>
...
</>);
this.setState(state);
}
render(): React.ReactNode {
return (<div><article>
{ this.state.news.element }
</article></div>);
}
}
export default NewsDetail;
错误信息
Compiled with problems:
ERROR
[eslint]
src\pages\news\detail.tsx
Line 14:25: React Hook "useParams" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
解决方案
做一个withRouter
通用函数,伪装成组件,取到hook后传给实际组件。
diff(/src/pages/news/index.tsx
):
@@ -11,7 +11,7 @@ class NewsDetail extends React.Component {
constructor(props: NewsDetailProps) {
super(props);
let state = this.state;
- state.news.number = useParams().id as string;
+ state.news.number = props._params.id;
state.news.element = (<>
<Grid.Row justify='center'>
<Typography.Title heading={ 1 }>{ state.news.title }</Typography.Title>
diff(/src/util/with_router.tsx
):
@@ -0,0 +1,8 @@
+import { useParams } from "react-router-dom";
+function withRouter(Child) {
+ return (props) => {
+ let params = useParams();
+ return <Child { ...props } _params={ params } />;
+ }
+}
+export { withRouter };
发生原因
React官方强推函数组件,没有像Vue那样的平滑过渡。
本人习惯用类组件,看不惯函数组件,于是搞了这个……
(点名批评React)(狂赞Vue)