最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - When should I use a custom equality function in useSelector()? - Stack Overflow

matteradmin8PV0评论

I'm trying to understand when it is necessary to use a custom equality function in useSelector().

I have a selector that returns a simple object as:

const data = useSelector(state => state.data) // => { a: "foo", b: "bar" }

I though that since data is an object, I needed to use a custom equality function to avoid unnecessary re-render, as it is stated in the doc:

With useSelector(), returning a new object every time will always force a re-render by default.

But then I noticed that my ponent was only re-rendering when data changed. I assumed that maybe the default equality function works with objects, but to be sure I tried to use a custom function:

const data = useSelector(state => state.data, (a, b) => a === b));

If data didn't change, it will always return true.

In Javascript, if I try to pare two objects with === it will return false because the references are different. But here with useSelector(), since it returns true it means that the references are the same.

Now, I'm not sure if I misunderstood the doc, but I wonder when I should use a custom equality function such as the isEqual of Lodash?

I'm using Redux Toolkit, if it makes any difference. Here is a CodeSandox if you want to test.

I'm trying to understand when it is necessary to use a custom equality function in useSelector().

I have a selector that returns a simple object as:

const data = useSelector(state => state.data) // => { a: "foo", b: "bar" }

I though that since data is an object, I needed to use a custom equality function to avoid unnecessary re-render, as it is stated in the doc:

With useSelector(), returning a new object every time will always force a re-render by default.

But then I noticed that my ponent was only re-rendering when data changed. I assumed that maybe the default equality function works with objects, but to be sure I tried to use a custom function:

const data = useSelector(state => state.data, (a, b) => a === b));

If data didn't change, it will always return true.

In Javascript, if I try to pare two objects with === it will return false because the references are different. But here with useSelector(), since it returns true it means that the references are the same.

Now, I'm not sure if I misunderstood the doc, but I wonder when I should use a custom equality function such as the isEqual of Lodash?

I'm using Redux Toolkit, if it makes any difference. Here is a CodeSandox if you want to test.

Share Improve this question edited Apr 23, 2023 at 6:24 Arkellys asked Jul 2, 2022 at 16:50 ArkellysArkellys 7,9214 gold badges21 silver badges48 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4

You should rarely need to write a custom equality function for useSelector.

Most of your useSelector calls should either be a simple const item = useSelector(state => state.slice.item), or be pass in an existing memoized selector function like const someData = useSelector(selectSomeData).

If you need to pass in a custom equality function, the most mon one would be the shallowEqual function exported from React-Redux itself.

If you think you need to use a deep equality check like _.isEqual, you should probably pause and reconsider why you think you need a deep equality check, because that should normally be unnecessary in a Redux app.

Additionally, I think there's a bit of a misunderstanding here. Yes, state.data is an object, but it is a reference to an object in memory. When your reducer updates, RTK+Immer will automatically create a new object reference, and thus oldObject === newObject will be false because two different objects are never === to each other. That's why useSelector already uses a === parison by default - immutable updates means that parison is really fast and simple to do.

Post a comment

comment list (0)

  1. No comments so far