Khi làm việc với React.js, bạn chắc chắn sẽ gặp useEffect
– một trong những hook quan trọng nhất giúp xử lý các tác vụ nằm ngoài quy trình render. Bài viết này sẽ giúp bạn hiểu rõ useEffect
là gì, khi nào nên dùng, cách viết đúng, và các ví dụ thực tế thường gặp trong dự án React.
1. Cách hoạt động cơ bản của useEffect.
useEffect(() => { // Thực hiện logic ở đây return () => { // Hàm clean-up, được gọi khi component unmount hoặc trước khi effect chạy lại };
}, [dependency1, dependency2]);
useEffect sẽ chạy sau khi component render xong.
Nếu bạn cung cấp một mảng dependencies, effect chỉ chạy lại khi giá trị trong mảng thay đổi.
Nếu mảng rỗng [], effect chỉ chạy một lần sau khi component mount
2. Các trường hợp sử dụng Hook UseEffect trong ReactJS.
2.1. Gọi API để lấy dữ liệu.
Đây là một trong những use case phổ biến nhất. Khi component được render, ta gọi API và cập nhật state với dữ liệu nhận được:
useEffect(() => { fetch('https://api.example.com/products') .then(res => res.json()) .then(data => setProducts(data));
}, []);
Giúp hiển thị dữ liệu động khi trang được load.
2.2. Cập nhật tiêu đề trang (document title)
Bạn có thể sử dụng useEffect để cập nhật tiêu đề trang tùy theo trạng thái của component:
useEffect(() => { document.title = `Bạn có ${notifications} thông báo mới`;
}, [notifications]);
Điều này nâng cao trải nghiệm người dùng, đặc biệt với các ứng dụng nhiều nội dung hoặc hệ thống quản trị.
2.3. Thêm và gỡ bỏ event listener
Khi cần xử lý các sự kiện như resize, scroll, keydown, bạn nên dùng useEffect để thêm event listener và đảm bảo dọn dẹp đúng cách:
useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); };
}, []);
Tránh rò rỉ bộ nhớ và lỗi logic khi component bị unmount.
2.4. Debounce hoặc throttle input của người dùng.
Trong các ô tìm kiếm hoặc form nhập liệu, bạn có thể debounce để tránh gọi API liên tục khi người dùng gõ phím:
useEffect(() => { const timeout = setTimeout(() => { search(query); // gọi API tìm kiếm }, 500); return () => clearTimeout(timeout);
}, [query]);
Giúp cải thiện hiệu xuất và giảm tải cho server.
2.5. Kết nối WebSocket hoặc Subscriptions
Với các ứng dụng thời gian thực (chat, theo dõi đơn hàng, bảng điều khiển live data), bạn cần kết nối WebSocket hoặc đăng ký (subscribe) dịch vụ:
useEffect(() => { const socket = new WebSocket('wss://example.com'); socket.onmessage = (event) => { setData(JSON.parse(event.data)); }; return () => socket.close();
}, []);
Giúp component luôn được cập nhật dữ liệu mới nhất từ server.
3. Fetch dữ liệu từ API bằng useEffect
Khi cần lấy dữ liệu từ API, useEffect giúp đơn giản hóa quy trình xử lý bất đồng bộ trong React. Bạn chỉ cần viết logic gọi API bên trong hàm callback của useEffect, sau đó cập nhật state thông qua useState.
useEffect(() => { async function fetchData() { const res = await fetch('https://api.example.com/data'); const json = await res.json(); setData(json); } fetchData();
}, []);
4. Cập nhật tiêu đề tài liệu với useEffect
Việc cập nhật tiêu đề trang (document title) là một thao tác phổ biến nhằm phản ánh trạng thái hiện tại của ứng dụng:
useEffect(() => { document.title = `Trang hiện tại: ${currentPage}`;
}, [currentPage]);
Bạn cũng nên dọn dẹp hiệu ứng khi không còn cần thiết để tránh lỗi hoặc rò rỉ bộ nhớ.
5. Lắng nghe sự kiện và clean-up.
Bạn có thể sử dụng useEffect để thêm event listener (ví dụ keydown, scroll,...) và gỡ bỏ khi component bị hủy:
useEffect(() => { const handleKeyDown = (e) => { if (e.key === 'Escape') closeModal(); }; document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('keydown', handleKeyDown); };
}, []);
6. Debounce/throttle input với useEffect.
Khi người dùng nhập liệu nhanh (ví dụ ô tìm kiếm), bạn có thể debounce để giảm số lần gọi API không cần thiết:
useEffect(() => { const timeout = setTimeout(() => { if (inputValue) { fetchSuggestions(inputValue); } }, 300); return () => clearTimeout(timeout);
}, [inputValue]);
7. Đăng ký dữ liệu theo thời gian thực (WebSocket, Subscriptions).
Với ứng dụng thời gian thực, bạn có thể dùng useEffect để tạo và quản lý các kết nối như WebSocket:
useEffect(() => { const socket = new WebSocket('wss://example.com'); socket.onmessage = (event) => { const newData = JSON.parse(event.data); setLiveData(newData); }; return () => socket.close();
}, []);
8. Kết luận
Hook useEffect trong React là một công cụ cực kỳ mạnh mẽ để xử lý các side effects trong component hàm. Với useEffect, bạn có thể:
-
Gọi API và cập nhật state.
-
Cập nhật tiêu đề trang web.
-
Quản lý và dọn dẹp event listeners.
-
Debounce hoặc throttle input.
-
Thiết lập kết nối WebSocket và nhận dữ liệu thời gian thực.
Việc sử dụng đúng useEffect, cùng với kiến thức vững về dependency array, cleanup function và cách hook hoạt động, sẽ giúp bạn viết code sạch, tối ưu và dễ bảo trì hơn trong các ứng dụng React hiện đại.
Hy vọng qua bài viết các bạn có thể hiểu hơn về cách hoạt động của useEffect trong react js