Search code examples
javascriptreactjsreduxreact-reduxreselect

How can I access useParams value inside redux selector as ownProps


  • I am using "reselect" library in redux to get the data. I wanna get data based on useParams() hook and then to pass it inside mapStatetoProps as ownProps and then to selectionCollection function which is a selector and accepts the value of useParams(). Apparently, it doesn't recognize the useParams() as ownProps and eventually returns undefined. btw, If I pass a string inside selectionCollection('someString), I receive the data but not using useParams() hook. I do receive the useParams value successfully but can't use it inside mapStateToProps which I think is a scope problem. I did define a global variable but didn't work.

import { connect } from 'react-redux';.

import { Outlet, useParams } from 'react-router-dom';

import { selectCollection } from '../../redux/shop/Shop-selectors';

const CollectionPage = ({ collection }) => {
  const params = useParams();
  const paramsId = params.collectionId;
  console.log(collection);
  
  return (
    <div className="collection-page">
      <p>THis is the collection page for {paramsId}</p>
      <Outlet />
    </div>
  );
};

//-- If I log the 'paramsId', I get undefined since it's outside the function

const mapStateToProps = (state, ownProps) => ({
// here is where I wanna use the paramsId as ownProps
  collection: selectCollection(ownProps.paramsId)(state),
});
export default connect(mapStateToProps)(CollectionPage);


Solution

  • I think you can achieve this in different ways but I suggest you two ways to use a params that comes from useParams Hook and mix it with react redux

    1- Create another top level component to get the router params in that and pass them to the CollectionPage component, so in the mapStateToProps you can access those params like this:

    const TopLevelCollectionPage = () => {
      const params = useParams();
    
      <CollectionPage params={params}></CollectionPage>;
    };
    
    const CollectionPage = ({ collection }) => {
      return (
        <div className="collection-page">
          <p>THis is the collection page</p>
          <Outlet />
        </div>
      );
    };
    
    const mapStateToProps = (state, ownProps) => ({
      collection: selectCollection(ownProps.params.collectionId)(state),
    });
    export default connect(mapStateToProps)(CollectionPage);
    

    2- using react redux hooks to get state inside of your component

    const CollectionPage = () => {
      const params = useParams();
      const collection = useSelector((state) =>
        selectCollection(params.collectionId)(state)
      );
      //or
      //const collection = useSelector(selectCollection(params.collectionId));
    };