Reputation: 6491
I wrote a useReduxState hook, which looks like this:
import { useSelector } from 'react-redux';
const pick = (object, keys) =>
keys.reduce(
(obj, key) => (object && Object.prototype.hasOwnProperty.call(object, key) ? { ...obj, [key]: object[key] } : obj),
{},
);
export default (reducer, values) =>
pick(
useSelector((state) => state[reducer]),
values,
);
I use this as,
const Component = React.memo(() => {
const { someStateFromReducerA, someMoreStateFromReducerA } = useReduxState('reducerA', ['someStateFromReducerA', 'someMoreStateFromReducerA']);
const { someStateFromReducerB } = useReduxState('reducerB', ['someStateFromReducerB']);
return (
<div>
{someStateFromReducerA}
{someMoreStateFromReducerA}
{someStateFromReducerB}
</div>
);
});
export default Component;
Although this seems like a convenient approach, I'm wondering if there is a difference between this approach and the below approach:
const Component = React.memo(() => {
const [
someStateFromReducerA,
someMoreStateFromReducerA
] = useSelector(
({ reducerA: { someStateFromReducerA, someMoreStateFromReducerA } }) =>
[someStateFromReducerA, someMoreStateFromReducerA]
);
const someStateFromReducerB = useSelector(({ reducerB: { someStateFromReducerB } }) => someStateFromReducerB);
return (
<div>
{someStateFromReducerA}
{someMoreStateFromReducerA}
{someStateFromReducerB}
</div>
);
});
export default Component;
Are there more re-renders with useReduxState
? I plan on using this hook across many different modules in different components, and I'm wondering if anything else is affected, such as more redundant references being created to state, causing rerenders.
Upvotes: 3
Views: 341
Reputation: 16234
Your hook is far less performant.
It will literally rerender more often. The useSelector()
is optimized to not rerender if the value is the same as the previous value. In your case you call useSelector()
selecting the entire reducer instead of just picking out what you need. It will rerender each time anything in the reducer changes.
The overhead to pick out the keys on each render is significant. You can remedy this with the useMemo()
hook to reduce the picking to just when something changes, but it still needs to do some picking when it does change.
Your 2nd example of usage of useSelector()
is even worse. Since it creates a new array every time, it results in non-equal return values and will rerender on each action.
My recommendation: use the useSelector()
hook multiple times in the component with each returning a minimal unit of data. Don't batch the selection.
Upvotes: 3