如何在 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

您想在一个地方访问staterouting 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 如何使用

我如何在类函数中获取 mapStateToProps 道具

如何访问 mapDispatchToProps 中 mapStateToProps 添加的属性?

React Native mapStateToProps未设置state + Redux

在 react-router v6 的 mapStateToProps 中使用 urlParams