Home > OS >  How can I get more than one value from the Redux store in a single statement?
How can I get more than one value from the Redux store in a single statement?

Time:03-31

I have this code:

const { user } = useSelector((state) => state.userReducer);
const { other } = useSelector((state) => state.otherReducer);

How could I get in one line those two (or more) values from the store?

const { user, other } = useSelector((state) => ?);

CodePudding user response:

const { user, other } = useSelector((state) => ({ 
  user: state.userReducer,
  other: state.otherReducer
}))

If you use lodash:

import { pick, isEqual } from 'lodash-es';

const { userReducer, otherReducer } = useSelector(
  (state) => pick(state, ['userReducer', 'otherReducer']), 
  isEqual
)

The second param (isEqual) is aimed at resolving the potential performance issue mentioned by @NicholasTower (and is equivalent to react-redux's shallowEqual).
Without a shallow object equality function, the component will re-render every time any mutation is committed to that store, regardless of key.

CodePudding user response:

The naive way to do it on one line would be to write a function that grabs the parts of state you care about, and constructs an object with those properties:

const { user, other } = useSelector((state) => {
  return { user: state.userReducer, other: state.otherReducer };
});

However, this will immediately cause a performance problem. Every time the selector runs, it creates a brand new object. And even if user and other havn't changed, the outer object has changed, so your component is forced to rerender. In other words, your component will rerender every time any action is dispatched anywhere in the app.

To fix this, useSelector allows you to provide an additional function which defines whether two values are equal or not. You can then implement a function to check if the stuff you care about has changed:

const { user, other } = useSelector((state) => {
  return { user: state.userReducer, other: state.otherReducer };
}, (a, b) => {
  return a.user === b.user && a.other === b.other
});

react-redux comes with a shallow comparison function which may be useful for this purpose if you prefer:

import { useSelector, shallowEqual } from 'react-redux';
// ...

const { user, other } = useSelector((state) => {
  return { user: state.userReducer, other: state.otherReducer };
}, shallowEqual);

CodePudding user response:

Would suggest using array instead of objects to avoid repeating keys

const [user, other] = useSelector(state => [state.userReducer, state.otherReducer])

CodePudding user response:

Meh, it was:

  const { userReducer: { user }, otherReducer: { other } } = useSelector((state) => state);
  • Related