use reselect with two or three parameters?

95 Views Asked by At

This is an example from reselect documents

const selectItemsByCategory = createSelector(
  [
    state => state.items,
    (state, category) => category
  ],
  (items, category) => items.filter(item => item.category === category)
)

usage on react

  const myitems = useSelector(
    (state) => selectItemsByCategory(state, 'CatName')
  )

My question is, how can I pass more than one parameter?

const selectChildItemByNameAndCategoryName = createSelector(
  [
    selectItemsByCategory
    (state, childName) => childName
  ],
  (categories, childName) => categories.filter... using childName form results of selectItemsByCategory
)

how can I use it?

  const myitems = useSelector(
    (state) => selectChildItemByNameAndCategoryName(state, 'CatName', 'childName')
  )
2

There are 2 best solutions below

0
Lin Du On

createSelector always forwards all arguments to all input selectors.

import { createSelector } from 'reselect';

const selectItemsByCategory = createSelector(
  [
    (state) => state.items,
    (state, category, childName) => {
      console.log(' ~ file: index.ts:7 ~ category:', category);
      console.log(' ~ file: index.ts:7 ~ childName:', childName);
      return category;
    },
  ],
  (items, category) => items.filter((item) => item.category === category),
);

const selectChildItemByNameAndCategoryName = createSelector(
  [
    selectItemsByCategory,
    (state, category, childName) => {
      console.log(' ~ file: index.ts:19 ~ category:', category);
      console.log(" ~ file: index.ts:19 ~ childName:", childName)
      return childName;
    },
  ],
  (items, childName) => items.filter((item) => item.childName === childName),
);

const data = selectChildItemByNameAndCategoryName(
  {
    items: [
      { category: 'a', childName: 'x' },
      { category: 'a', childName: 'y' },
      { category: 'b', childName: 'x' },
    ],
  },
  'a',
  'x',
);
console.log(data);

Output:

 ~ file: index.ts:7 ~ category: a
 ~ file: index.ts:7 ~ childName: x
 ~ file: index.ts:19 ~ category: a
 ~ file: index.ts:19 ~ childName: x
[ { category: 'a', childName: 'x' } ]
0
Arya The Developer On

In your case, you can simply just do this:

const selectChildItemByNameAndCategoryName = createSelector(
      [
        selectItemsByCategory,
        (state, childName) => childName,
        (state, childName, catName) => catName
      ],
      (categories, childName, catName) => categories.filter... using childName form results of selectItemsByCategory
    )

So, in your component, you can position the arguments in a similar order:

const myitems = useSelector((state) => selectChildItemByNameAndCategoryName(state, 'childName', 'CatName'))