React useEffect
Hooks
useEffect
Hook cho phép bạn thực hiện các tác dụng phụ trong các thành phần của mình.
Một số ví dụ về tác dụng phụ là: tìm nạp dữ liệu, cập nhật trực tiếp DOM và tính giờ.
useEffect
chấp nhận hai đối số. Đối số thứ hai là tùy chọn.
useEffect(<function>, <dependency>)
Hãy sử dụng bộ đếm thời gian làm ví dụ.
Ví dụ:
Sử dụng setTimeout()
để đếm 1 giây sau lần hiển thị đầu tiên:
import { useState, useEffect } from "react"; import ReactDOM from "react-dom/client"; function Timer() { const [count, setCount] = useState(0); useEffect(() => { setTimeout(() => { setCount((count) => count + 1); }, 1000); }); return <h1>I've rendered {count} times!</h1>; } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Timer />);
Nhưng chờ đã!! Nó cứ đếm mặc dù nó chỉ nên đếm một lần!
useEffect
chạy trên mọi kết xuất. Điều đó có nghĩa là khi số lượng thay đổi, một kết xuất sẽ xảy ra, sau đó sẽ kích hoạt một hiệu ứng khác.
Đây không phải là điều chúng tôi muốn. Có một số cách để kiểm soát thời điểm xảy ra tác dụng phụ.
Chúng ta phải luôn bao gồm tham số thứ hai chấp nhận một mảng. Chúng ta có thể tùy ý chuyển các phần phụ thuộc cho useEffect
trong mảng này.
Ví dụ
1. Không có phần phụ thuộc nào được thông qua:
useEffect(() => { //Runs on every render });
Ví dụ
2. Một mảng trống:
useEffect(() => { //Runs only on the first render }, []);
Ví dụ
3. Đạo cụ hoặc giá trị trạng thái:
useEffect(() => { //Runs on the first render //And any time any dependency value changes }, [prop, state]);
Vì vậy, để khắc phục sự cố này, chúng ta chỉ chạy hiệu ứng này trên kết xuất ban đầu.
Ví dụ:
Chỉ chạy hiệu ứng trên kết xuất ban đầu:
import { useState, useEffect } from "react"; import ReactDOM from "react-dom/client"; function Timer() { const [count, setCount] = useState(0); useEffect(() => { setTimeout(() => { setCount((count) => count + 1); }, 1000); }, []); // <- add empty brackets here return <h1>I've rendered {count} times!</h1>; } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Timer />);
Ví dụ:
Đây là một ví dụ về useEffect
Hook phụ thuộc vào một biến. Nếu biến count
cập nhật, hiệu ứng sẽ chạy lại:
import { useState, useEffect } from "react"; import ReactDOM from "react-dom/client"; function Counter() { const [count, setCount] = useState(0); const [calculation, setCalculation] = useState(0); useEffect(() => { setCalculation(() => count * 2); }, [count]); // <- add the count variable here return ( <> <p>Count: {count}</p> <button onClick={() => setCount((c) => c + 1)}>+</button> <p>Calculation: {calculation}</p> </> ); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Counter />);
Nếu có nhiều phần phụ thuộc thì chúng phải được đưa vào mảng phụ thuộc useEffect
.
Được chứng nhận!
$95 ĐĂNG KÝ
Dọn dẹp hiệu ứng
Một số hiệu ứng yêu cầu dọn dẹp để giảm rò rỉ bộ nhớ.
Thời gian chờ, đăng ký, trình xử lý sự kiện và các hiệu ứng khác không còn cần thiết nữa sẽ bị loại bỏ.
Chúng tôi thực hiện điều này bằng cách thêm hàm trả về vào cuối useEffect
Hook.
Ví dụ:
Dọn dẹp bộ đếm thời gian khi kết thúc useEffect
Hook:
import { useState, useEffect } from "react"; import ReactDOM from "react-dom/client"; function Timer() { const [count, setCount] = useState(0); useEffect(() => { let timer = setTimeout(() => { setCount((count) => count + 1); }, 1000); return () => clearTimeout(timer) }, []); return <h1>I've rendered {count} times!</h1>; } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Timer />);
Lưu ý: Để xóa bộ đếm thời gian, chúng tôi phải đặt tên cho nó.