Reputation: 621
I have the following situation:
A selector for a list of countries in my app state
export const getCountries = state => state.countries;
And a selector created using reselect to filter for a country with a specific id
export const getCountryById = countryId =>
createSelector(
[getCountries],
(countries) => {
let countriesList = countries.filter(c => c.id === countryId);
if ( countriesList ) {
return countriesList[0];
}
return null;
}
)
Then a have a country details page component ( acessed through http://localhost:3000/country/4 )
import React from 'react';
import { getCountryById } from '../redux/selectors';
import { connect } from 'react-redux';
const CountryPage = ({country}) => {
return <h1>{country.name}</h1>
}
const mapStateToProps = (state, ownProps) => {
console.log(ownProps.match.params.countryId);
const obj = {
country: getCountryById(ownProps.match.params.countryId)
}
return obj;
};
export default connect(mapStateToProps, null)(CountryPage);
The mapStateToProps is correctly receiving the countryId, but the selector is not being called. What am I missing here ?
Or is it the wrong approach to using the selectors ? I am aware that I can use the full country list from state in the CountryPage and filter it there, but what is the best practice here ?
Upvotes: 0
Views: 1055
Reputation: 67459
That's because your getCountryById
isn't actually a selector. It's a function that returns a selector.
Given that you are trying to use a unique ID per component, and doing filtering, you probably need to use the "factory function" form of mapState
to create a unique selector instance per component instance to get proper memoization behavior.
However, having said that, your selector can also be simplified. You don't need a filter()
here, you need a find()
, and that means it's also not something that really needs to be memoized. This can be simplified down to:
const getCountryById = createSelector(
[getCountries, (state, id) => id],
(countries, id) => countries.find(c => c.id === id) || null
)
and then used as:
const mapStateToProps = (state, ownProps) => {
return {
country: getCountryById(state, ownProps.match.params.countryId)
}
};
Upvotes: 1