React Tutorials
React ES6
React Hooks
useCallback
HookReact useCallback
Hook returns a memorization function.
Think of memorization as keeping the value so that it does not need to be recalculated.
This allows us to separate the in-depth functions of the app so that it does not work automatically across all offers.
The useCallback
Hook only works when one dependent is updated.
This can improve performance.
useCallback
and useMemo
Hooks are the same. The main difference is that useMemo
returns a memorized value and useCallback
returns a memorized function. You can learn more about using useMemo in the Memo chapter.
One reason to use useCallback
is to prevent the component from being re-rendered unless its resources are changed.
In this example, you might think that part of Todos
will never give up again unless todos
changes:
This is the same example as in the React.memo section.
index.js
import { useState } from "react";
import ReactDOM from "react-dom";
import Todos from "./Todos";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<>
<Todos todos={todos} addTodo={addTodo} />
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
</div>
</>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
Todos.js
import { memo } from "react";
const Todos = ({ todos, addTodo }) => {
console.log("child render");
return (
<>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</>
);
};
export default memo(Todos);
Try using this and click the calculate button.
You will notice that the Todos
section also offers even when the todos
do not change.
Why does this not work? We use memo
, so part of Todos
should not re-render as todos
status or addTodo
function changes when the number goes up.
This is due to something called "referential equality".
Each time a part donates, its functions are rebuilt. As a result, the function of addTodo
has really changed.
To fix this, we may use the useCallback
hook to prevent the work from being redone unless necessary.
Use the useCallback
Hook to prevent part of Todos
from redundant:
index.js
import { useState, useCallback } from "react";
import ReactDOM from "react-dom";
import Todos from "./Todos";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = useCallback(() => {
setTodos((t) => [...t, "New Todo"]);
}, [todos]);
return (
<>
<Todos todos={todos} addTodo={addTodo} />
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
</div>
</>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
Todos.js
import { memo } from "react";
const Todos = ({ todos, addTodo }) => {
console.log("child render");
return (
<>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</>
);
};
export default memo(Todos);
Now part of Todos
will re-offer only when todos
prop changes.