【问题标题】:How to use useParams in mapStateToProps?如何在 mapStateToProps 中使用 useParams?
【发布时间】: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

标签: reactjs react-redux react-router-dom


【解决方案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/stackoverflowhow-to-use-useparams-in-mapstatetoprops-qxxdo?file=/src/article-page.js:87-225

      【讨论】:

        猜你喜欢
        • 2020-06-05
        • 2021-11-14
        • 1970-01-01
        • 2020-04-22
        • 1970-01-01
        • 1970-01-01
        • 2020-12-27
        • 2022-08-18
        • 2021-06-27
        相关资源
        最近更新 更多