26

When I should use useCallback and when simple array function? Or maybe I shouldn't use second approach?

const MyCompenent = (props) => {
  const handleClick = useCallback(()=>{
    //do stuff
  })
  return(
    <SomeCompnent onClick={handleClick} />
  )
}
// or
const MyCompenent = (props) => {
  return(
    <SomeCompnent onClick={()=> {/*do stuff*/}} />
  )
}
2
  • It is basic that the first approach makes the code look clearer at least from template perspective. Commented Sep 27, 2019 at 7:47
  • 3
    My general rule is if the component is mounted once, displays some stuff and the result of the onClick handler is the component is unmounted, then the second, otherwise I do the first for performance and readability. In the first the callback/handler is only bound to this once, but won't get rebound on subsequent renders. Commented Sep 27, 2019 at 7:49

2 Answers 2

17

To add to Rajesh's great answer, it really boils down to how much optimization is needed on the child components.

In our experience of deploying a large-scale application in React (millions of users), the more important check for Performance is the Profiler (which was added in the new React Dev Tools with a nifty flame graph), rather than React's re-renders, as well as network fetches (IE: unnecessary fetches, bad API's, or fetches that could be run concurrently instead of sequentally).

React Re-render != DOM Re-render

At some point many developers got obsessed with React's rendering (partially I believe because of the option of highlighting renders).

In fact, Facebook is not so interested in bringing highlights back because of said confusion I believe.

In our company, it also happened to some devs that thought that renders from certain components were the bottleneck (which in my opinion, they were looking at the wrong place).

But that also came from a lack of understanding that React's renders can be very, very cheap, which are completely different from creating or destroying HTML nodes which can become expensive.

They (as many people do) erroneously thought that renders were recreating the HTML DOM tree, which was not the case.

Imagine that at some point someone said that most of our components should be PureComponents. We have hundreds of components, so that's a bit of a stretch!

Our team hardly ever uses PureComponents or ReactMemo, yet most of our containers work really well even under heavy loads.

So, coming back to the point, yes, in components where we are doing expensive computations on renders, but most importantly that were highly coupled to the UX, we decided to work on optimization. For everyday Joe and Alice components, we trust React.

NOTE: Also, do notice that React's Development Mode is considerably slower than Production. I was surprised when I was raised the issue at work that some Page was running slowly, and the benchmark was done in Development mode! (The issue didn't go any further as Production was running absolutely fine).

Sign up to request clarification or add additional context in comments.

Comments

15

As per docs,

Pass an inline callback and an array of dependencies. useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).

What this means is, given a pure function and dependencies, the output will remain same for given set of arguments/ dependencies. So what it does is save the output for given set and if such call is made, instead of calling the actual function, directly previously calculated value is returned.


In your example, you are not passing any dependencies. So its very similar to a simple function but with an extra layer of wrapping.

You can use a named function or an inline function for handler. Which to use falls as a personal opinion, however I prefer having a named function as it keeps JSX clean and gives a possibility of reusability.

References:

1 Comment

"So what it does is save the output for given set" you seem to conflagrate useCallback and useMemo. As your example link ends, "useCallback(f, []) is equivalent to useMemo(() => f, [])". That is, the function is the cached output. Any use of OPs handleClick will call the actual function, its execution is never skipped with useCallback.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.