Trong bài viết này, chúng ta sẽ tìm hiểu về useCallback
- một hook quan trọng trong React. useCallback
giúp chúng ta tối ưu hiệu suất của ứng dụng bằng cách tránh việc tạo lại các hàm không cần thiết.
useCallback
là một hook trong React giúp chúng ta tạo ra một hàm memoized, nghĩa là hàm này chỉ được tạo lại khi một trong các dependencies thay đổi.
Cú pháp của useCallback
như sau:
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
Trong đó, doSomething(a, b)
là hàm cần được memoize, và [a, b]
là danh sách các dependencies.
Trong React, khi một component re-render, tất cả các hàm bên trong component đó đều được tạo lại. Điều này có thể gây ra vấn đề về hiệu suất, đặc biệt khi chúng ta đang sử dụng các hàm trong các hook như useEffect
hoặc useMemo
.
Với useCallback
, chúng ta có thể tránh được việc tạo lại các hàm không cần thiết, từ đó tăng hiệu suất của ứng dụng.
Dưới đây là một ví dụ về cách sử dụng useCallback
:
import React, { useState, useCallback } from 'react';
function App() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
Count: {count}
<button onClick={increment}>Increment</button>
</div>
);
}
export default App;
Trong ví dụ trên, hàm increment
chỉ được tạo lại khi count
thay đổi, giúp tăng hiệu suất của ứng dụng.
Trong React, một vấn đề phổ biến mà các lập trình viên thường gặp phải là việc không kiểm soát được việc re-render của component. Điều này thường xảy ra khi chúng ta truyền một function qua một component khác như một prop.
Giả sử chúng ta có hai component: ParentComponent
và ChildComponent
. ParentComponent
truyền một function handleClick
qua ChildComponent
như một prop.
import React, { useState } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<ChildComponent onClick={handleClick} />
</div>
);
}
function ChildComponent({ onClick }) {
console.log('ChildComponent re-rendered!');
return (
<button onClick={onClick}>Click me</button>
);
}
Trong ví dụ trên, mỗi lần ParentComponent
re-render, một function handleClick
mới sẽ được tạo ra và truyền qua ChildComponent
. Điều này dẫn đến việc ChildComponent
cũng sẽ re-render mỗi lần ParentComponent
re-render, ngay cả khi prop onClick
không thay đổi.
Để giải quyết vấn đề này, chúng ta có thể sử dụng hook useCallback
của React. useCallback
sẽ trả về một version memoized của function mà chỉ thay đổi nếu một trong các dependencies thay đổi.
import React, { useState, useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<ChildComponent onClick={handleClick} />
</div>
);
}
function ChildComponent({ onClick }) {
console.log('ChildComponent re-rendered!');
return (
<button onClick={onClick}>Click me</button>
);
}
Trong ví dụ trên, handleClick
chỉ sẽ thay đổi khi count
thay đổi. Điều này đảm bảo rằng ChildComponent
chỉ sẽ re-render khi prop onClick
thay đổi, giúp cải thiện hiệu suất của ứng dụng.
useCallback
là một công cụ hữu ích để tối ưu hiệu suất của ứng dụng React. Tuy nhiên, hãy nhớ rằng không phải lúc nào chúng ta cũng cần sử dụng useCallback
. Chỉ sử dụng nó khi thực sự cần thiết, để tránh làm phức tạp hóa code.