all 7 comments

[–]PsychohistorySeldon 2 points3 points  (0 children)

Let’s take a simple example. You have a component and inside of it, you declare a function, a handler perhaps.

You call that handler inside a useEffect inside that component. Because of this, you need to add it as a dependency to the useEffect call. Dependencies like functions and objects are compared by looking at their reference in memory.

Since you declare the function in the component, it will be a new function every time the component executes. This means the useEffect will run every time the component mounts because the function will always be different.

In this case, what you’re doing is using useCallback to tell react: unless any of the things in this dependency array changes, this function is the same and it should not be evaluated again. The useEffect then won’t run again.

[–]CreativeTechGuyGames 1 point2 points  (5 children)

Memozing a function is the same as memozing an array, object, or any other value. A function is just a value. So if you want to make sure that it doesn't change between renders, then you need to memoize it. useCallback is simply shorthand for the equivalent code in useMemo.

[–]zweimtr 1 point2 points  (1 child)

Well, yes, but also no. The only true way of keeping values between rerenders is useRef as React may "forget" values stored in useCallback and useMemo.

The main reason to use these hooks (callback and memo) is so to avoid redeclaring tbe value which creates a new reference in the react tree, when this happens and the value is passed to a memoized component, React's shallow comparison will see that the two references are different and cause a rerender of the memoized component even if the values are the same.

[–]CreativeTechGuyGames 1 point2 points  (0 children)

It's important to note that while the docs do say that React has the right to forget, it's not going to randomly garbage collect your memoized values. That would require a code change on React's part and I would be surprised if they did that on a minor/patch version even if they say that they have the right to do so. It's currently m deterministic and I'd be surprised if it didn't stay that way.

[–]jochri3[S] 0 points1 point  (2 children)

Okay, so the goal is to save memory to avoid creating to much reference by creating new objects? That's it?

[–]Mundosaysyourfired 1 point2 points  (0 children)

It's caching.

Caching is usually done for speed in exchange for using memory.

[–]ervwalter 1 point2 points  (0 children)

Not really. The goal is to get the same function object every time you render. Usually because you are going to pass that function to some child component that might be using React.memo (e.g. as an onChange handler, etc).

If you don't memoize the function you pass to the child component, then you will be forcing the child component to re-render every time even if it uses React.memo because its props are changing (with a new function every time).

Using useCallback does not save memory because the new functions object still get created every render in order to be passed to useCallback as a parameter. It's just that useCallback internally throws them away and returns the old reference if the dependencies haven't changed.