React useEffectHooks


Hook cho phép bạn thực hiện các hiệu ứng useEffectphụ trong các thành phần của bạn.

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à bộ tính giờ.

useEffectchấ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ụ.

Thí dụ:

Sử dụng setTimeout()để đếm 1 giây sau khi kết xuất ban đầu:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

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

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  });

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById('root'));

Nhưng chờ đã !! Tôi tiếp tục đếm mặc dù nó chỉ nên đếm một lần!

useEffectchạy trên mọi kết xuất. Điều đó có nghĩa là khi số lượng thay đổi, kết xuất sẽ xảy ra, điều này sau đó sẽ kích hoạt một hiệu ứng khác.

Đây không phải là những gì chúng tôi muốn. Có một số cách để kiểm soát khi các tác dụng phụ chạy.

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ụ thuộc vào useEffecttrong mảng này.

1. Không có phụ thuộc nào được thông qua:

useEffect(() => {
  //Runs on every render
});

2. Một mảng trống:

useEffect(() => {
  //Runs only on the first render
}, []);

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 hãy chỉ chạy hiệu ứng này trên kết xuất ban đầu.

Thí 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";

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>;
}

ReactDOM.render(<Timer />, document.getElementById('root'));

Thí dụ:

Đây là một ví dụ về một useEffectHook phụ thuộc vào một biến. Nếu countbiến cập nhật, hiệu ứng sẽ chạy lại:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

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>
    </>
  );
}

ReactDOM.render(<Counter />, document.getElementById('root'));

Nếu có nhiều phần phụ thuộc, chúng nên được đưa vào useEffectmảng phụ thuộc.


w3schools CERTIFIED . 2022

Được chứng nhận!

Hoàn thành các mô-đun React, làm bài tập, làm bài kiểm tra và được chứng nhận w3schools !!

$ 95 GHI DANH

Xóa hiệu ứng

Một số hiệu ứng yêu cầu dọn dẹp để giảm rò rỉ bộ nhớ.

Hết thời gian chờ, đăng ký, trình nghe sự kiện và các hiệu ứng khác không còn cần thiết nên được xử lý.

Chúng tôi thực hiện điều này bằng cách bao gồm một hàm trả về ở cuối useEffectHook.

Thí dụ:

Dọn dẹp bộ đếm thời gian ở cuối useEffectHook:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

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>;
}

ReactDOM.render(<Timer />, document.getElementById("root"));

Lưu ý: Để xóa bộ đếm thời gian, chúng tôi phải đặt tên cho nó.


Kiểm tra bản thân với các bài tập

Bài tập:

Bạn cần thêm gì vào đối số thứ hai của useEffectHook để giới hạn nó chỉ chạy trong lần hiển thị đầu tiên?

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

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

  useEffect(() => {
    setData(getData())
  }, );

  return <DisplayData data={data} />;
}

ReactDOM.render(<App />, document.getElementById('root'));