Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass an additional argument to useSelector

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);
like image 781
Andy Hoffman Avatar asked Jun 24 '20 00:06

Andy Hoffman


People also ask

Does useSelector trigger re render?

With useSelector() , returning a new object every time will always force a re-render by default. If you want to retrieve multiple values from the store, you can: Call useSelector() multiple times, with each call returning a single field value.

Can you use a selector in a reducer?

It's not typically possible to use selectors inside of reducers, because a slice reducer only has access to its own slice of the Redux state, and most selectors expect to be given the entire Redux root state as an argument.

What does useSelector return?

useSelector and useDispatch are a set of hooks to use as alternatives to the existing connect() higher-order component. The equivalent of map state to props is useSelector. It takes in a function argument that returns the part of the state that you want.

Are selectors memoized?

The result will be stored in the memory, and it will be fetched only if the value doesn't change. Each selector has its own memoization, meaning it cannot cache multiple selectors.


1 Answers

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));
like image 120
buzatto Avatar answered Oct 06 '22 22:10

buzatto