Hướng dẫn sử dụng Hook useTimeout trong React
Giới thiệu
Trong bài viết này, chúng ta sẽ tìm hiểu cách tạo một Hook tùy chỉnh trong React có tên là useTimeout. Hook này sẽ giúp chúng ta dễ dàng sử dụng hàm setTimeout(callback, delay) với một số tính năng bổ sung hữu ích. Mục tiêu của chúng ta là:
- Đặt lại bộ đếm thời gian nếu thời gian trễ (
delay) thay đổi. - Không đặt lại thời gian nếu hàm gọi lại (
callback) thay đổi.
Mã nguồn khởi tạo
Dưới đây là mã nguồn khởi tạo cho Hook useTimeout:
javascript
export function useTimeout(callback: () => void, delay: number) {
// your code here
}
// Nếu bạn muốn thử mã của mình trên bảng điều khiển bên phải
// hãy nhớ xuất component App() như bên dưới
// export function App() {
// return <div>your app</div>
// }
Cách hoạt động của Hook useTimeout
Bước 1: Lưu trữ hàm gọi lại
Bước đầu tiên là lưu hàm gọi lại mới nhất trong một ref. Điều này đảm bảo rằng setTimeout sẽ luôn gọi phiên bản mới nhất của hàm:
javascript
const savedCallback = useRef(callback);
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
Bước 2: Xử lý thời gian trễ
Tiếp theo, chúng ta cần xử lý thời gian trễ. Khi thời gian trễ là null, bộ đếm thời gian sẽ không chạy. Ngược lại, chúng ta cần đặt một setTimeout mới khi thời gian trễ thay đổi. Chúng ta cũng nên có một hàm dọn dẹp để đảm bảo các bộ đếm thời gian cũ được xóa khi thời gian trễ thay đổi hoặc component bị gỡ bỏ:
javascript
useEffect(() => {
if (delay == null) return;
const id = setTimeout(() => {
savedCallback.current();
}, delay);
return () => clearTimeout(id);
}, [delay]);
Mã hoàn chỉnh
Để thử nghiệm, chúng ta sẽ có 2 nút thiết lập thời gian trễ lần lượt là 1s và 3s. Mã hoàn chỉnh sẽ trông như sau:
javascript
import React, { useEffect, useRef, useState } from "react";
export function useTimeout(callback: () => void, delay: number) {
const savedCallback = useRef(callback);
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
if (delay == null) return;
const id = setTimeout(() => {
savedCallback.current();
}, delay);
return () => clearTimeout(id);
}, [delay]);
}
export function App() {
const [count, setCount] = useState(0);
const [delay, setDelay] = useState(3000);
useTimeout(() => {
console.log("Timeout fired:", count);
setCount((c) => c + 1);
}, delay);
return (
<div>
<p>{count}</p>
<button onClick={() => setDelay(1000)}>Đặt thời gian trễ 1s</button>
<button onClick={() => setDelay(3000)}>Đặt thời gian trễ 3s</button>
</div>
);
}
Thực hành và kiểm tra
Hãy thử nghiệm mã trên để xem cách hoạt động của Hook useTimeout. Khi bạn nhấn vào các nút, bạn sẽ thấy số đếm tăng lên sau mỗi khoảng thời gian trễ mà bạn đã thiết lập.
Thực tiễn tốt nhất
- Luôn kiểm tra các giá trị đầu vào: Đảm bảo rằng các giá trị
callbackvàdelaylà hợp lệ trước khi sử dụng. - Thực hiện dọn dẹp: Đảm bảo rằng các bộ đếm thời gian cũ được xóa để tránh rò rỉ bộ nhớ.
Những cạm bẫy thường gặp
- Không kiểm tra giá trị null: Nếu không kiểm tra giá trị
delay, có thể dẫn đến việc gọi hàm khi không mong muốn. - Bỏ qua dọn dẹp: Nếu không thực hiện dọn dẹp, có thể làm cho ứng dụng của bạn không hoạt động hiệu quả.
Mẹo tối ưu hiệu suất
- Sử dụng
useCallback: Khi sử dụng Hook này, nếu có thể, hãy sử dụnguseCallbackđể tránh việc tạo ra hàm mới mỗi lần render. - Giảm tần suất cập nhật: Đặt thời gian trễ hợp lý để tránh gọi hàm quá thường xuyên.
FAQ
1. Hook useTimeout có thể sử dụng cho những trường hợp nào?
Hook này hữu ích trong các tình huống cần xử lý thời gian như đếm ngược, chờ tải dữ liệu, hoặc thực hiện các hành động sau một khoảng thời gian nhất định.
2. Có cách nào để hủy bỏ setTimeout không?
Có, bạn có thể sử dụng hàm dọn dẹp mà chúng ta đã định nghĩa trong useEffect để hủy bỏ setTimeout khi component bị gỡ bỏ hoặc khi delay thay đổi.
Kết luận
Bài viết đã hướng dẫn bạn cách tạo và sử dụng Hook useTimeout trong React. Hãy thử nghiệm và áp dụng vào dự án của bạn để nâng cao trải nghiệm người dùng. Nếu có bất kỳ câu hỏi nào, đừng ngần ngại để lại câu hỏi trong phần bình luận bên dưới!
Kêu gọi hành động
Hãy chia sẻ bài viết này với bạn bè và đồng nghiệp của bạn nếu bạn thấy nó hữu ích. Cùng nhau phát triển kỹ năng lập trình của chúng ta!