类组件内的 react-router-dom useParams()
Posted
技术标签:
【中文标题】类组件内的 react-router-dom useParams()【英文标题】:react-router-dom useParams() inside class component 【发布时间】:2020-02-21 05:32:00 【问题描述】:我正在尝试加载基于 react-router-dom 路由的详细信息视图,该路由应获取 URL 参数 (id) 并使用它来进一步填充组件。
我的路由看起来像/task/:id
,并且我的组件加载正常,直到我尝试从 URL 中获取 :id,如下所示:
import React from "react";
import useParams from "react-router-dom";
class TaskDetail extends React.Component
componentDidMount()
let id = useParams();
this.fetchData(id);
fetchData = id =>
// ...
;
render()
return <div>Yo</div>;
export default TaskDetail;
这会触发以下错误,我不确定在哪里正确实现 useParams()。
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
文档仅显示基于功能组件的示例,而不是基于类的示例。
【问题讨论】:
钩子在基于类的组件中不起作用 @Dupocas 好的,这是有道理的。您会建议什么,将类重写为函数或使用类并尝试以其他方式获取 url 参数? 两个有效的选择。您可以发布useParams
的代码吗?也许把它变成HOC
?
谁能评论一下为什么这仅限于功能组件?我已经使用 React 大概 8 个月了,像这样的事情对我来说仍然是一个常规的“陷阱”,很想更好地理解它。
React Route v6 中的函数:***.com/a/70251443/624533
【参考方案1】:
您可以使用withRouter
来完成此操作。只需将导出的分类组件包装在withRouter
中,然后您可以使用this.props.match.params.id
来获取参数,而不是使用useParams()
。您还可以使用withRouter
获取任何location
、match
或history
信息。都是在this.props
下传入的
使用您的示例,它看起来像这样:
import React from "react";
import withRouter from "react-router";
class TaskDetail extends React.Component
componentDidMount()
const id = this.props.match.params.id;
this.fetchData(id);
fetchData = id =>
// ...
;
render()
return <div>Yo</div>;
export default withRouter(TaskDetail);
就这么简单!
【讨论】:
在 react router dom v6 中使用 withRouter 时出现错误:Attempted import error: 'withRouter' is not exported from 'react-router-dom'
是的,看起来 v6 不再使用它了。您仍然可以从react-router
导入它。我将更新我的答案以反映这一点
react-router
也不包含withRouter
。我得到了同样的错误结果
这里是使用它的docs。也许这会有所帮助【参考方案2】:
参数通过匹配对象上的道具传递。
props.match.params.yourParams
来源:https://redux.js.org/advanced/usage-with-react-router
以下是文档中的一个示例,它破坏了参数中的道具。
const App = ( match: params ) =>
return (
<div>
<AddTodo />
<VisibleTodoList filter=params.filter || 'SHOW_ALL' />
<Footer />
</div>
)
【讨论】:
这似乎是一个非常干净的解决方案,可以避免钩子,但有什么警告吗?为什么 react-router 文档没有提到这个作为替代方案,而只在文档中显示了 hooks 示例?【参考方案3】:You can not call a hook 例如来自 React.Component 的“useParams()”。
如果您想使用钩子并拥有现有的 react.component,最简单的方法是创建一个函数,然后从该函数调用 React.Component 并传递参数。
import React from 'react';
import useParams from "react-router-dom";
import TaskDetail from './TaskDetail';
function GetId()
const id = useParams();
console.log(id);
return (
<div>
<TaskDetail taskId=id />
</div>
);
export default GetId;
你的切换路线仍然是这样的
<Switch>
<Route path="/task/:id" component=GetId />
</Switch>
那么你就可以从你的 react 组件中的 props 中获取 id
this.props.taskId
【讨论】:
一个衬里Route
和 Component
有效,而不是 <Route>code</Route>
无效,为什么会这样?
在import语句中应该是useParams而不是useParams。【参考方案4】:
由于钩子不适用于基于类的组件,您可以将其包装在一个函数中并传递属性:
class TaskDetail extends React.Component
componentDidMount()
const id = this.props.params;
// ...
export default (props) => (
<TaskDetail
...props
params=useParams()
/>
);
但是,就像@michael-mayo 所说,我希望这就是withRouter
已经在执行的操作。
【讨论】:
【参考方案5】:React Route v5
可以使用withRouter
和queryString
将查询参数作为JSON 读取和处理,如下所示:
import React from "react";
import withRouter from "react-router";
import queryString from 'query-string';
class MyComponent extends React.Component
componentDidMount()
const params = queryString.parse(this.props.location.search);
console.log('Do something with it', params);
render()
return <div>Hi!</div>;
export default withRouter(MyComponent);
【讨论】:
【参考方案6】:在 react-router-dom v6 中,没有诸如 withRouter 之类的钩子,因此我的建议是将基于类的组件转换为功能组件以使用 useParams 挂在你的组件中。
【讨论】:
...这里是一个如何做到的例子:Edit react-router-v5-to-v6-compatibility【参考方案7】:React Route v6
我的朋友们,我试图在课堂上使用,但我没有找到任何关于它的文档。因此,经过数小时的搜索和努力,这就是(功能)。现在(即当我写这篇文章时)关于 v6 的资源有限。但是 这里我使用的是 useState、useEffect、useParams、axios。 注意:
我遇到了 useEffect 循环。我用钥匙阻止了它。 希望:这可能对某人有所帮助! 参考:import React, useState, useEffect from 'react';
import useParams from 'react-router-dom';
import axios from 'axios';
const Post = () =>
let post_id = useParams();
const [posts, setPosts] = useState( post: null, countSecrets: 0, ui: '' );
useEffect(() =>
if (posts.countSecrets === 0)
const doAxe = (a) =>
axios.get('https://jsonplaceholder.typicode.com/posts/' + post_id)
.then((res) =>
setPosts(s => ( ...s, value: res.data ));
doUI(res.data)
// console.log(res.data)
);
setPosts(s => ( ...s, countSecrets: s.countSecrets + 1 ));
doAxe()
, [posts, post_id]);
let doUI = (x) =>
// console.log('x' + x.title)
const finalPost = (x !== null) ? (
<div className="post">
<h4 className="center">x.title</h4>
<p>x.body</p>
</div>
) : (
<div className="center">Loading posts...</div>
);
setPosts(s => ( ...s, ui: finalPost ));
return (
<div className="container">
posts.ui
</div>
);
export default Post;
【讨论】:
【参考方案8】:import React, Component from "react";
import useParams from "react-router-dom";
function withParams(Component)
return props => <Component ...props params=useParams() />;
class TaskDetail extends React.Component
componentDidMount()
let id = this.props.params;
this.fetchData(id);
fetchData = id =>
// ...
;
render()
return <div>Yo</div>;
export default withParams(TaskDetail);
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于类组件内的 react-router-dom useParams()的主要内容,如果未能解决你的问题,请参考以下文章
React redirect - react-router-dom 上的重定向组件
导入使用 React-Router-Dom 的自定义模块组件时出现问题