Федор Усаков
Федор Усаков

Reputation: 1255

How to? Creating Redux selectors with arguments

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

Answers (3)

Alistair Green
Alistair Green

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

Arshabh Agarwal
Arshabh Agarwal

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

Dmitriy Kovalenko
Dmitriy Kovalenko

Reputation: 3616

You can keep your logic inside mapStateToProps

function mapStateToProps (state) {
  return {
    entity: state.data.filter((entity) => entity.id === state.selecetedId)
  }
}

Upvotes: 1

Related Questions