How to pass an additional argument to useSelector
Asked Answered
C

4

39

I am calling useSelector successfully from a component, which derives a product name from an id.

const productId = 25; // whatever

const productName = useSelector(
  (state) =>
    state.dashboard.dashboards.filter(
      ({ Id }) => Id === productId
    )[0].Name
);

However, my selector is dependent on productId, which I'm storing in a variable in the same file. I'd like to store this useSelector call in an external file so it can be shared. I tried the following, but id is undefined:

selectors.js

export const getProductNameById = (store, id) => {
  return store.dashboard.dashboards.filter(({ Id }) => Id === id)[0]
    .Name;
}

some_file.js

import { useSelector } from "react-redux";
import { getProductNameById } from "./selectors";

const productId = 25;
const productName = useSelector(getProductNameById, productId);
Creaturely answered 24/6, 2020 at 0:10 Comment(0)
A
97

unfortunately, selector function accepts only store's state as argument. I would consider to use a currying approach to tackle the issue:

export const getProductNameById = id => store => {
  return store.dashboard.dashboards.filter(({ Id }) => Id === id)[0]
    .Name;
}

some file

import { useSelector } from "react-redux";
import { getProductNameById } from "./selectors";

const productId = 25;
const productName = useSelector(getProductNameById(productId));
Araroba answered 24/6, 2020 at 1:23 Comment(1)
If you're using reselect for your selectors, this will cause the selector to be called on every single render, as the getProductNameById(productId) call itself isn't memoized.Scrivner
O
53

Seems like the way to do this would be like this:

const productName = useSelector((state) => getProductNameById(state, productId));

This is the how redux docs tutorial seems to handle this. here

Osteoma answered 1/8, 2020 at 8:6 Comment(0)
M
0

This works fine for me.

export const getProductNameById = id => store => {
  return store.dashboard.dashboards.filter(({ Id }) => Id === id)[0]
    .Name;
}

Then you can call this using:

 const productName = useSelector(state => getProductNameById (id)(state));
Monarski answered 18/5 at 11:15 Comment(0)
D
-5

This should also work:

const productName = useSelector(getProductNameById(productId));
Downey answered 25/8, 2021 at 16:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.