如何在 mapStateToProps 中使用 useParams?
Posted
技术标签:
【中文标题】如何在 mapStateToProps 中使用 useParams?【英文标题】:How to use useParams in mapStateToProps? 【发布时间】:2021-03-10 00:11:19 【问题描述】:我想要路由参数中的特定道具并使用它来过滤redux-store
中的数据。
Product.js
import React from 'react';
import useParams from 'react-router-dom';
import connect from 'react-redux';
const Product = (props) =>
let slug = useParams();
//console.log(props.match)
return (
<div>
<h3>Welcome to <b> slug </b> page</h3>
</div>
)
const mapStateToProps = ( state, ownProps ) =>
// let id = slug;
return item: state.items[0]
export default connect(
mapStateToProps
)(Product);
App.js
function App()
return (
<Router>
<Navbar/>
<Switch>
<Route exact path="/:slug">
<Product/>
</Route>
<Route exact path="/">
<Home/>
</Route>
</Switch>
</Router>
);
以及导航到/slug
路径的任何链接都以Product.js
结尾,因为Product.js
没有嵌套在其他任何地方,所以我无法获得特定的道具传递但路由参数。从我的角度来看,这是完全错误的,但我想不出更好的方法。
【问题讨论】:
你的 React 和 Redux 库的版本是多少? @ridoansaleh"react": "^17.0.1", "redux": "^4.0.5", "react-redux": "^7.2.2"
@ridoansaleh 在生产中,我认为我应该将slug
设置为有意义的东西,例如项目名称而不是 id 以获得网站排名 (SEO)。在这种情况下,我的 slug 应该是 name + id + generate random stuffs,最后从路由参数中提取 id 以使用它过滤数据细节。这真的是 React 开发者在现实世界中所做的吗?
是的,您应该将与您的目的相关的参数命名为 productID 或 productName
【参考方案1】:
由于您使用的是新版本的 React 和 Redux。您可以尝试使用 Hook 从 redux 存储中获取数据。
最好调用 useSelector。阅读更多here
import React from "react";
import useParams from "react-router-dom";
import useSelector from "react-redux";
const Product = () =>
let slug = useParams();
const item = useSelector((state) => state.items[slug]);
console.log(item);
return (
<div>
<h3>
Welcome to <b>slug</b> page
</h3>
</div>
);
;
export default Product;
【讨论】:
【参考方案2】:在您的情况下,您可以使用mapDispatchToProps
属性,它是connect
的第二个参数
Product.js
import React, useState, useEffect from 'react';
import useParams from 'react-router-dom';
import connect from 'react-redux';
const Product = (props) =>
const slug = useParams();
const
items, // From mapStateToProps
filterItems // From mapDispatchToProps
= props;
const [filteredItems, setFilteredItems] = useState([]);
useEffect(() =>
setFilteredItems(filterItems(items, slug));
);
return (
<div>
<h3>Welcome to <b> slug </b> page</h3>
<!-- filteredItems.map(item => ) -->
</div>
)
const mapStateToProps = ( state, ownProps ) =>
return items: state.items
const mapDispatchToProps = dispatch =>
return
filterItems: (items, filter) =>
// TODO: Filter logic goes here...
return items;
;
export default connect(
mapStateToProps,
mapDispatchToProps
)(Product);
【讨论】:
【参考方案3】:另一个高效的解决方案是使用withRouter
您想在一个地方访问
state
和routing params
以从状态中选择您想要的内容。
一种解决方案是在组件内部使用useParams
,当您使用connect
访问状态时,这很好。
但是,我曾经发现这个解决方案会导致我的组件重新渲染很多,因为我们不会悄悄地控制useParams
被重新调用的方式,我更喜欢使用HOC(higher order component)
react-router-dom
提供称为 withRouter
(我发现它的性能更高),这里是如何使用它
你把它包裹在连接上
import withRouter from "react-router-dom";
...
export const ArticlePageContainer = withRouter(
connect(mapStateToProps, undefined)(ArticlePageUI)
);
然后您可以在mapStateToProps
函数中从props
内部访问slug
或任何params
function mapStateToProps(state, props)
const slug = props.match.params.slug;
return
targetArticle: state.items.find((item) => item.slug == slug)
;
最后,您可以在组件中使用该选定的数据,您现在可以直接从props
获取它。
function ArticlePageUI(props)
return (
<>
<p>"Article Page"</p>
<p>props.targetArticle?.content</p>
</>
);
这是一个代码沙盒,您可以在其中自己检查实现 https://codesandbox.io/s/***how-to-use-useparams-in-mapstatetoprops-qxxdo?file=/src/article-page.js:87-225
【讨论】:
以上是关于如何在 mapStateToProps 中使用 useParams?的主要内容,如果未能解决你的问题,请参考以下文章
如何导出 mapStateToProps 和 Redux 表单?
React-redux mapStateToProps,mapDispatchToProps 如何使用
如何访问 mapDispatchToProps 中 mapStateToProps 添加的属性?