In my application, I want to pass the parameter that I'm getting from useParams()
to the mapStateToProps
function which I'm using with the Reselect library.
I can hard code the value instead of passing this parameter and everything works as expected. Also, I can pass useParams().routeName
directly to the mapState
function and it's working. But in case of using ownProps
, it is not working. Here is my code:
const CollectionPage = ({collection}) => {
let params = useParams();
let collectionPath = params.routeName;
return (
<div className='collection-page'>
</div>
)
}
const mapStateToProps = (state, ownProps) => ({
collection: selectCollection(ownProps.collectionPath)(state)
});
export default connect(mapStateToProps)(CollectionPage);
With this code, the return will be undefined, but when I hard code the value, like the code below, it’s working:
const mapStateToProps = (state) => ({
collection: selectCollection(''Some Hard Coded Value'')(state)
});
The preferred method would be to use the React hooks directly in the component. Instead of using the connect
Higher-Order Component (HOC), use the useSelector
hook to select/access the collection
state. Refactor the selectCollection
selector to return the state and do the filtering in the UI.
Example:
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
const CollectionPage = () => {
const { routeName } = useParams();
const collection = useSelector(state => {
const collection = selectCollection(state);
// Logic to return collection filtered by routeName, etc...
return <UI value here>
});
return (
<div className='collection-page'>
...
</div>
);
};
If you have the need to access path parameters in any mapStateToProps
function, and if you are using a lot of other code, for example, then you'll need to create another HOC to access the path parameters and have them injected as props so they are available in the mapStateToProps
function.
Example:
import { useParams, /* Other hooks */ } from "react-router-dom";
const withRouter = Component => props => {
const params = useParams();
// Other hooks, useLocation, useNavigate, etc..
return <Component {...props} {...{ params, /* other injected props */ }} />;
};
export default withRouter;
...
import { compose } from 'redux';
import { connect } from 'react-redux';
import withRouter from '../path/to/withRouter';
const CollectionPage = ({ collection }) => {
return (
<div className='collection-page'>
...
</div>
);
};
const mapStateToProps = (state, { params: { routeName } = {} }) => ({
collection: selectCollection(routeName)(state),
});
export default compose(
withRouter, // <-- injects a params prop
connect(mapStateToProps) // <-- props.params accessible
)(BlogDetailsPage);