reactjsreact-hooksreact-router-domreselectmapstatetoprops

How do I pass a URL Param to a selector


I recive a url param from useParams. I want to pass it to a selector using mapStateToProps.

collection.component.jsx

import { useParams } from "react-router-dom";
import { connect } from "react-redux";

import { selectShopCollection } from "../../redux/shop/shop.selectors";

import './collection.styles.scss'

const Collection = ({ collection }) => {
  const { collectionId } = useParams();
  console.log(collection)
  return (
    <div>
      <h1>{collection}</h1>
    </div>
  )
}

const mapStateToProps = (state, ownProps) => ({
  collection: selectShopCollection(ownProps.match.params.collectionId)(state)
})

export default connect(mapStateToProps)(Collection);

shop.selectors.js

import { createSelector } from "reselect"

const selectShop = state => state.shop

export const selectShopCollections = createSelector([selectShop], shop =>
  shop.collections
)

export const selectShopCollection = collectionUrlParam =>
  createSelector([selectShopCollections], collections =>
    collections.find(collection => collection.id === collectionUrlParam)
  )

I guess the problem is that, I cannot pass params using match as react-router-dom v6 does not pass it in props. Is there any other way to pass collectionId to the selector selectShopCollection?


Solution

  • Since Collection is a function component I suggest importing the useSelector hook from react-redux so you can pass the collectionId match param directly. It simplifies the component API. reselect selectors work well with the useSelector hook.

    import { useParams } from "react-router-dom";
    import { useSelector } from "react-redux";
    
    import { selectShopCollection } from "../../redux/shop/shop.selectors";
    import './collection.styles.scss'
    
    const Collection = () => {
      const { collectionId } = useParams();
      const collection = useSelector(selectShopCollection(collectionId));
    
      console.log(collection);
    
      return (
        <div>
          <h1>{collection}</h1>
        </div>
      )
    };
    
    export default Collection;