Does useCallback hook create a function everytime a component renders in React.js?
Asked Answered
C

3

9

During the job interview, I was asked how to optimize a component in React.

So I answered with an example of using useCallback and useMemo hooks.

Because whenever a components re-renders, functions and variables declared inside of the component are newly created which results in those newly created values occupying memory space.

However, with a help of those two hooks, it is possible to save memory because using useCallback and useMemo prevents creating the function and variable again and again by saving and reusing the previous result, as long as a state inside the dependency array is not changed during the component re-rendering.

So far, this was my answer. But the interviewer said useCallback does not prevent creating a function. Even if useCallback is used, a function is still created.

I do not get this part. How is the function created again inside the useCallback hook?

Is there something I'm missing about useCallback and useMemo?

Coincidentally answered 2/9, 2021 at 12:8 Comment(3)
See my explanation below, please ask if you are not clear at any points. I will try to make that more understandable from your feedbacks.Craniometry
@RyanLe Thank you for the detail explanation with the example below. What I understand from Khalt's comment is that even using useCallback hook, a function is still re-created however it does not re-create a new reference in the memory. Instead the function is re-assigned to the same reference before?Coincidentally
Functions are objects, and every newly created object are different in term of memory allocation. With useCallback. Functions are not re-created but the variable (changeWithUseCallback) that reference to useCallback in the function does. Which also mean that the function inside useCallback is always the same in every renders.Craniometry
C
3

Here I made an example so you can see useCallback in action:

In the example bellow: useCallback will prevent newly changeWithUseCallback re-create every new render, result that Child1 never gets re-render because it's props (changeWithUseCallback) never re-created.

Otherwise, in the Child2 component, its prop (changeWithoutUseCallback) is always re-created during renders, so the component itself will re-render.

Please note that React.memo will skip rendering the component if its props have not changed

So I would say that you are right about useCallback that it will keep the function/variable reference during renders, or prevent creating new function/variable during renders.

function App() {
  const [value, setValue] = React.useState(0);
  const changeWithUseCallback = React.useCallback(() => {
    console.log("onChangeChild");
  }, []);
  const changeWithoutUseCallback = () => {
    console.log("onChangeChild");
  };
  return (
    <div className="App">
      <button type="button" onClick={() => setValue(value + 1)}>
        Change value
      </button>
      <h1>{value}</h1>
      <Child1 onChange={changeWithUseCallback} />
      <Child2 onChange={changeWithoutUseCallback} />
    </div>
  );
}

const Child1 = React.memo(({ onChange }) => {
  console.log("Child1 render!!!");
  return null;
});

const Child2 = React.memo(({ onChange }) => {
  console.log("Child2 render!!!");
  return null;
});

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Craniometry answered 2/9, 2021 at 12:50 Comment(2)
From my understanding, the function/variable is still re-created. After all, the entire component gets rerendered/re-exectued -> the variables are declared and set every single time. The only difference is that they end up referencing the same place in memory.Rescission
Reassign could be a better word in this case since recreate means having a new reference.Craniometry
V
1

It does recreate the function. But, it uses the reference to the function that's created earlier, given no dependency is changed. So, that might prevent re-rendering of child component or triggering another hook that has the function in its dependency array.

Valora answered 11/12, 2022 at 18:13 Comment(0)
D
1

If you think about it, both useMemo and useCallback recreates function on every rerender.

const temp1 = useMemo(() => {return console.log('a')}, [])
const temp2 = useCallback(() => {console.log('a')}, [])

when we pass function declarations to useMemo and useCallback, () => {console.log('a')} this part will always be ran. (unless react compiling process changes something - which is unlikely since compilation process is mostly jsx transpiling)

Then what do they actually do to improve performance?

  • useMemo caches the result of a function call. However, It always seems to recreate the function itself on every rerender.

  • useCallback caches the reference of a function. It also always seems to recreate the function on every rerender.

useCallback is mostly used to

  1. keep reference value to skip rerendering children
  2. keep reference value to reduce useEffect calls

for example codes of these two, take a look at the Usage part of the official doc

Dermatologist answered 7/4 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.