ReactJS - Sử dụng useCallback: Hướng dẫn cho người mới bắt đầu

Xin chào, những nhà phát triển React tương lai! Hôm nay, chúng ta sẽ cùng tìm hiểu một trong những hook mạnh mẽ của React: useCallback. Đừng lo lắng nếu bạn mới bắt đầu học lập trình; tôi sẽ hướng dẫn bạn từng bước qua khái niệm này, giống như tôi đã làm cho nhiều học sinh trong những năm dạy học của mình. Hãy cùng bắt đầu hành trình thú vị này nhé!

ReactJS - Using useCallback

useCallback là gì?

Trước khi chúng ta đi sâu vào chi tiết, hãy hiểu useCallback là gì. Hãy tưởng tượng bạn đang nướng bánh quy (tôi thích ví dụ này vì, à, ai lại không thích bánh quy phải không?). Bạn có một công thức đặc biệt mà bạn sử dụng mỗi lần. useCallback giống như việc viết xuống công thức đó một lần và sử dụng nó mỗi khi bạn cần nướng bánh quy, thay vì cố gắng nhớ nó mỗi lần.

Trong thuật ngữ React, useCallback là một hook giúp chúng ta tối ưu hóa hiệu suất ứng dụng của mình bằng cách ghi nhớ (memoizing) các hàm.

Định dạng của hook useCallback

Hãy xem cách chúng ta viết useCallback:

const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);

Đừng lo lắng! Tôi biết rằng điều này có thể trông phức tạp, nhưng chúng ta sẽ phân tích nó:

  1. memoizedCallback: Đây là hàm mà useCallback trả về.
  2. () => { doSomething(a, b); }: Đây là hàm mà chúng ta muốn ghi nhớ.
  3. [a, b]: Đây được gọi là mảng phụ thuộc. Nó告诉 React khi nào tạo lại hàm của chúng ta.

Hãy nghĩ về nó như này: Bạn đang nói với React, "Hey, ghi nhớ hàm này cho tôi, và chỉ cho tôi một hàm mới nếu a hoặc b thay đổi."

Áp dụng useCallback

Bây giờ, hãy xem useCallback trong hành động với một ví dụ đơn giản:

import React, { useState, useCallback } from 'react';

function Counter() {
const [count, setCount] = useState(0);

const increment = useCallback(() => {
setCount(c => c + 1);
}, []);

return (
<div>
Count: {count}
<button onClick={increment}>Increment</button>
</div>
);
}

Hãy phân tích điều này:

  1. Chúng ta import useCallback từ React.
  2. Chúng ta tạo một biến trạng thái count sử dụng useState.
  3. Chúng ta định nghĩa một hàm increment sử dụng useCallback. Hàm này sẽ tăng giá trị của count lên 1.
  4. Mảng trống [] làm tham số thứ hai có nghĩa là hàm này sẽ không bao giờ thay đổi.
  5. Chúng ta hiển thị count và một nút tăng giá trị khi được nhấn.

Các trường hợp sử dụng useCallback

Bây giờ bạn có thể tự hỏi, "Khi nào我应该使用 useCallback?" Đó là một câu hỏi tuyệt vời! Hãy xem xét một số tình huống phổ biến:

1. Truyền các hàm回调 đến các thành phần con được tối ưu hóa

Hãy tưởng tượng bạn có một thành phần con được bao bọc bởi React.memo (đừng lo lắng nếu bạn chưa hiểu rõ điều này, chúng ta sẽ covered nó trong các bài học sau). Bạn muốn truyền một hàm vào thành phần này:

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} />
<p>Count: {count}</p>
</div>
);
}

const ChildComponent = React.memo(({ onClick }) => {
console.log("Child rendered!");
return <button onClick={onClick}>Increment</button>;
});

Ở đây, useCallback đảm bảo rằng handleClick chỉ thay đổi khi count thay đổi, ngăn chặn việc render lại không cần thiết của ChildComponent.

2. Trong các phụ thuộc của useEffect

useCallback cũng hữu ích khi một hàm là phụ thuộc của một hook useEffect:

import React, { useState, useCallback, useEffect } from 'react';

function DataFetcher() {
const [data, setData] = useState(null);

const fetchData = useCallback(() => {
// Hãy tưởng tượng rằng đây là việc lấy dữ liệu từ một API
setTimeout(() => setData("New Data!"), 1000);
}, []);

useEffect(() => {
fetchData();
}, [fetchData]);

return <div>{data ? data : "Loading..."}</div>;
}

Trong ví dụ này, useCallback đảm bảo rằng fetchData không thay đổi trên mỗi render, ngăn chặn hiệu ứng từ chạy không cần thiết.

Ưu điểm và nhược điểm

Hãy tóm tắt các ưu và nhược điểm của useCallback:

Ưu điểm Nhược điểm
Ngăn chặn việc render lại không cần thiết Có thể làm cho mã phức tạp hơn
Tối ưu hóa hiệu suất cho các thành phần con Lạm dụng có thể dẫn đến vấn đề hiệu suất
Hữu ích trong các phụ thuộc của useEffect Cần hiểu biết về closure và ghi nhớ
Giúp tạo ra các callback ổn định Có thể không mang lại lợi ích显著 trong các thành phần đơn giản

Kết luận

Uf! Chúng ta đã cùng nhau đi qua rất nhiều nội dung hôm nay. useCallback là một công cụ mạnh mẽ trong bộ công cụ React của bạn, nhưng như bất kỳ công cụ nào, việc sử dụng nó khôn ngoan là rất quan trọng. Khi bạn tiếp tục hành trình học React, bạn sẽ phát triển trực giác cho việc khi nào nên sử dụng useCallback.

Nhớ rằng, tối ưu hóa là điều tuyệt vời, nhưng mã rõ ràng và dễ đọc còn quan trọng hơn. Đừng cảm thấy áp lực để sử dụng useCallback ở mọi nơi - hãy sử dụng nó khi nó có ý nghĩa cho ứng dụng của bạn.

Tiếp tục thực hành, giữ vững sự tò mò, và chúc bạn lập trình vui vẻ! Và nhớ rằng, giống như việc hoàn thiện một công thức bánh quy, việc thành thạo React cũng cần thời gian và sự kiên nhẫn. Bạn làm được đâu!

Credits: Image by storyset