DEV Community

Itay Schechner
Itay Schechner

Posted on • Edited on

You MUST use the useCallback hook!

Hi everyone! My name is Itay and I’m a fullstack developer who specializes in back-of-the-frontend React.js code.

In this shot, I’ll show you the usages of the useCallback hook for better performance of your application, and explain why you should use it.

For a start, let’s look at this code:

export function MyComponent () {
    const [numericState, setNumber] = useState(0);
    const handleClick = () => {
        setNumber(x => x%2 +1);
    }
    return (
        <>
        <button onClick={handleClick}>Click Me</button>
        {numbericState}
        </>
    )
}
Enter fullscreen mode Exit fullscreen mode

What’s wrong with this code? It’s not completely optimized. The handle click function is changing on every render!

That would be the equivalent of writing the following class based component:

export default class MyComponent extends React.Component {
  state: {
    numericState: 0
  }
  render() {
    const handleClick = () => {
        this.setState(({ numericState }) => ({ numericState: numericState%2 +1 }));
    }
    return (
        <>
          <button onClick={handleClick}>Click Me</button>
          {this.state.numbericState}
        </>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

This, of course, is ridiculous. A better practice would be to write your class-based component in the following way:

export default class MyComponent extends React.Component {
  state: {
    numericState: 0
  }
  handleClick = () => {
    this.setState(({ numericState }) => ({ numericState: numericState%2 +1 }));
  }
  render() {
    return (
        <>
          <button onClick={this.handleClick}>Click Me</button>
          {this.state.numbericState}
        </>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

The question is, how to you write it in a functional approach? This is what hooks are made for. Let’s see how we can write the functional component in an optimized way:

export function MyComponent () {
    const [numericState, setNumber] = useState(0);
    const handleClick = useCallback(() => {
        setNumber(x => x%2 +1);
    }, []); // works exactly like useEffect
    return (
        <>
        <button onClick={handleClick}>Click Me</button>
        {numbericState}
        </>
    )
}
Enter fullscreen mode Exit fullscreen mode

REMEMBER: Not using the useCallback hook = writing everything in you render function!

You can see a complex back-of-the-frontend React.js app I've recently built here

Top comments (12)

Collapse
 
nombrekeff profile image
Keff

How is the last example more optimized and why? In what ways is it different than not using useCallback? What benefits would this give me?

Much information missing for such a big title.

Collapse
 
itays123 profile image
Itay Schechner

I mentioned it in the article. The last example is more optimized because we don't recreate the click handle function on every rerender.

Collapse
 
nombrekeff profile image
Keff

I still don't understand, isn't this just re-creating the callback on each re-render as well?

const handleClick = useCallback(() => {
        setNumber(x => x%2 +1);
}, []); 
Enter fullscreen mode Exit fullscreen mode

How is this more efficient? I mean, you are still "re-creating" the callback on each render.

Correct me if I'm wrong, but as I understand, the only thing that useCallback does is memoize the function for the passed dependencies, so it seems in this particular case it is not optimizing anything as it does not know the about any dependency.

Thread Thread
 
itays123 profile image
Itay Schechner

Just read the hook documentation. I'm sure you have better things to do other than commenting discouraging comments on random posts.

Thread Thread
 
nombrekeff profile image
Keff

It was not my intention to discourage, sorry if it felt that way. But for having such a strong title, I felt the post was lacking information, that's all. No need to get angry or discouraged by this, I was hoping for a bit of a conversation about this.

Just read the hook documentation
I've checked the docs, and found not much information about why this particular example is more optimized, that's why I asked! Also, by the title I supposed this post would explain that in detail...

Again, I'm sorry if I sounded harsh or discouring. That's not my intention at all, but I hate these kinds of titles, even more if they don't offer that much value.

Thread Thread
 
itays123 profile image
Itay Schechner

I understand. There is a great explanation on why you should use it in a previous post I wrote, using websockets with React.js. I explained in detail how use Callback saved my life there.

Thread Thread
 
nombrekeff profile image
Keff

I will check it out! Cheers!

Thread Thread
 
exneval profile image
Egi Ginting • Edited

@nombrekeff

Check Kent C. Dodds article if you still not get it, (I'll just copy some part of it here below)

Q: So when should I useMemo and useCallback?
A: There are specific reasons both of these hooks are built-into React:

  1. Referential equality
  2. Computationally expensive calculations

And thanks for the article @itays123 , hope it can cover more complex cases and explanation in the future so some readers won't get the wrong idea of this hook, because premature code optimization can lead them to make thing worse

Thread Thread
 
nombrekeff profile image
Keff

Fantastic I'll check that out too, thanks for the info

Thread Thread
 
nombrekeff profile image
Keff

because premature code optimization can lead them to make thing worse

Yup, totally agree here, that was in part why I wanted to understand it better

Thread Thread
 
itays123 profile image
Itay Schechner

Already Archived and prepating a better one

Collapse
 
hassankhademi profile image
hassanKhademi

Great