Passing an argument to a selector in Redux toolkit

Tuesday, April 8, 2025

Intro

Redux toolkit uses Reselect out of the box for its selectors.

Reselect is library for creating memoized "selector" functions. Commonly used with Redux, but usable with any plain JS immutable data as well.

Passing an argument to a selector

This is a sample snippet in creating a selector that accepts a single argument projectId.

export const calendarProjectOptionsSelector = createSelector(
  calendarsSelector.selectAll,
  (_: RootState, projectId: string) => projectId,
  (calendars, projectId) => {
    const options: Option[] = calendars
      .filter((c) => c.projectId === projectId)
      .map((p) => ({
        value: p.id,
        label: p.name,
        tag: {
          label: p.name,
          color: p.color,
        },
      }));
    return options;
  },
);

How to use it

Just pass projectId as a second argument to the selector

const calendarOptions = useSelector((state: RootState) =>
  calendarProjectOptionsSelector(state, projectId),
);

Passing multiple values to a selector

This is a sample snippet in creating a selector that accepts multiple arguments projectId and ownerId.

export const groupedPackagesSelector = createSelector(
  activePackagesSelector,
  (
    _: RootState,
    { ownerId, projectId }: { ownerId: string; projectId: string },
  ) => ({
    ownerId,
    projectId,
  }),
  (packages, { ownerId, projectId }) => {
    const groupedPackages: GroupedPackage[] = [];
 
    packages
      .filter((p) => p.projectId === projectId)
      .forEach((p) => {
        if (!p.locked || (p.locked && ownerId === p.owner.id)) {
          groupedPackages.push({
            label: p.name,
            value: p.id,
            color: p.color,
            group: p.locked ? PackageGroup.Locked : PackageGroup.Public,
            code: p.code,
          });
        }
      });
 
    return groupedPackages;
  },
);

How to use it

Just pass projectId and ownerId in a object as a second argument to the selector

const groupedPackages = useSelector((state: RootState) =>
  groupedPackagesSelector(state, { ownerId, projectId }),
);

Conclusion

Reselect only allows you to pass a single argument to a selector, for you to be able to pass multiple values, you need to wrap those values into one object and pass it as a single argument.

You can read more in the official documentation of Reselect here.