Let's say we're making a webpage where we want to draw a smiley face every time we click a button.
But drawing that smiley takes a lot of computer energy.
So, we tell React to remember how to draw a smiley face using useCallback.
Now, every time we click the button, React 'remembers' how to draw the smiley without using extra energy
import React, { useCallback } from 'react';
function SmileyComponent() {
// This is our "spell" for drawing a smiley
const drawSmiley = useCallback(() => {
console.log("π");
}, []);
return (
<div>
{/* A button that, when clicked, will use the memorized drawSmiley function */}
<button onClick={drawSmiley}>Draw Smiley</button>
</div>
);
}
export default SmileyComponent;
Dependencies
Think of useCallback like a magic notebook for your robot friend that helps it remember how to do a task (like building a sandcastle) the best way possible, without wasting energy. But if something important changes (like the weather), the robot knows it needs to update its notebook with new instructions.
This way, your robot always builds the sandcastle perfectly, using the least amount of energy, and you both have more time to play and have fun at the beach!
import React from 'react';
const MyCustomButton = React.memo(({ onClick, children }) => {
console.log(`Rendering button: ${children}`);
return <button onClick={onClick}>{children}</button>;
});
import React, { useState, useCallback } from 'react';
function ColorBox() {
const [weather, setWeather] = useState('sunny'); // The weather condition
const [color, setColor] = useState('yellow'); // Color of the box
const updateColor = useCallback(() => {
switch (weather) {
case 'sunny':
setColor('yellow');
break;
case 'rainy':
setColor('gray');
break;
case 'windy':
setColor('blue');
break;
default:
setColor('green'); // Default color if weather is not recognized
}
}, [weather]); // The dependency array
return (
<div>
<h2>Weather: {weather}</h2>
<MyCustomButton onClick={() => setWeather('sunny')}>Sunny</MyCustomButton>
<MyCustomButton onClick={() => setWeather('rainy')}>Rainy</MyCustomButton>
<MyCustomButton onClick={() => setWeather('windy')}>Windy</MyCustomButton>
<MyCustomButton onClick={updateColor}>Update Box Color</MyCustomButton>
<div style={{ width: '100px', height: '100px', backgroundColor: color, marginTop: '20px' }}>
Box
</div>
</div>
);
}
export default ColorBox;
Conclusion
useCallback with dependencies is a smart way for things (like your robot or a computer program) to remember how to do something efficiently, only changing their plan when they really need to, based on what's different. !
Top comments (17)
Nice! I guess one of the key reasons that this is important is that if you pass the function as a prop to a child component, that child component will not re-render every time as the function doesn't keep changing each render.
Thank you for the insightful explanation of how useCallback works in React. The analogy of the magic notebook for the robot friend effectively communicates the concept of memoization and optimization of function re-creation.
The use of useCallback to memoize the drawSmiley function is a great example of how we can optimize performance by preventing unnecessary re-creation of the function on every render. This can be particularly useful in scenarios where the function is passed down to child components, ensuring that they don't re-render unless the dependencies change.
The analogy of the robot using the magic notebook to build a sandcastle efficiently, while updating its instructions based on changes, is a clever way to illustrate the benefits of memoization. It helps to make the concept more accessible and relatable, especially for those who are new to the idea of memoization in React.
Overall, it's a well-written explanation that effectively communicates the benefits of using useCallback in React to optimize performance. Thank you for sharing this insightful analogy!
Thank you :)
Let's gooo! π
haha you already know
I still loved the simple drawing analogy, also a good refresher, had forgotten there is such a hook π
I've been struggling with this problem for a while, and your article provided the clarity I needed to move forward. Thank you!
This made my entire day, you're welcome
Nice docs.
Unfortunately, this example doesn't showcase memorization of the function in any logical way.
To demonstrates the behaviour correctly, create a custom
MyCustomButton
component and see how many times each of the buttons update.Also, without React.memo the
MyCustomButton
will also keep updating.I don't mean to be bashing this post, but with the misleading title like you have posted, will be mislead.
You're absolutely correctβwithout React.memo, components will continue to update unnecessarily.
My initial focus was solely on implementing useCallback in the simplest manner possible for kids to understand without introducing other concepts.
However, I've since revised the code to include memo to enhance its accuracy.
Since we are already nitpicking, it's .memoize not memorize. I would hate for anyone who came here trying to learn about memoization techniques in React to be confused by your comment.
hahaha....i agree, his comment was nitpicking ...thanks for having my back there
didn't understand the dependency part clearly
No problem, it can take some time to get the hang of it:)
okay, so :
The twist in our dependency scenario involves adding a condition that, when changed, forces the function to "forget" its cached result and recompute it, possibly with adjustments based on the new condition.
For example, imagine we have a function that builds a sandcastle.
This function will memoize its result (the completed sandcastle) unless a specific condition changes (like the weather).
If the weather changes (from sunny to rainy), the function must re-run and adjust its process (because how you build sandcastle in sunny weather is different in rainy weather. Maybe you need to cover it or stop in rainy weather).
So in our case, weather is the dependency, because it dictates the running of our function.
Understood now, Thank you π
my pleasure :)