Reputation: 1255
I have a state with a map array of some data. I need to select one object from it. I can get the whole array using
function mapStateToProps (state) {
return {
allDataSet: state.data
}
}
and then select the entity needed placing logic in the component. Like this:
(id) => this.props.allDataSet.filter((entity) => entity.id === id)
But somehow I believe that doing this is wrong and against all of the best practices, as all selectors logic should be separated from the component.
Exactly this case is simple, but i real project I had to place complex selectors inside my component just to get data by Id...
Is there any patterns or best practices that provides solution for this?
Upvotes: 2
Views: 3188
Reputation: 472
If you want your selector to be reusable, then you can define it in a separate file:
export function getSelectedEntity(state) {
return state.data.filter((entity) => entity.id === state.selectedId)
}
Then import and call the selector function in your mapStateToProps()
:
function mapStateToProps(state) {
return {
entity: getSelectedEntity(state)
};
}
One advantage of this pattern is that you can easily write a unit test for the selector, since it is a pure function and is kept separate from your React component.
Consider using Reselect, which is a helper library for creating memoized selector functions.
Upvotes: 1
Reputation: 556
You should normalize allDataSet as an object and the keys should be the id of the entity.
function mapStateToProps (state) {
let allDataSet = {};
state.data.forEach((datum) => {
allDataSet[datum.id] = datum;
})
return {
allDataSet
}
}
Then you can access the needed entity just by this.props.allDataSet[id]
Take a look at this http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html
Upvotes: 2
Reputation: 3616
You can keep your logic inside mapStateToProps
function mapStateToProps (state) {
return {
entity: state.data.filter((entity) => entity.id === state.selecetedId)
}
}
Upvotes: 1