Chào các bạn, hôm nay chúng ta sẽ đi sâu vào useEffect() trong React Hooks, một công cụ mạnh mẽ cho phép chúng ta xử lý các side effects trong các component. Chúng ta sẽ không chỉ tìm hiểu cú pháp mà còn xem xét các tình huống sử dụng nâng cao và một số mẹo thực hành.

1. Khái Niệm Cơ Bản Về useEffect()

  • useEffect cho phép bạn thực hiện các tác vụ ngoài việc render, như gọi API, theo dõi sự kiện, và thao tác với DOM.
  • Side effects bao gồm bất kỳ hoạt động nào mà không phải chỉ là render lại component, ví dụ như:
    • Gọi một API để lấy dữ liệu.
    • Thiết lập một listener cho sự kiện.
    • Cập nhật tiêu đề của trang.

2. Cú Pháp useEffect

useEffect(() => {
  // Code cho side effect
  return () => {
    // Clean-up code
  };
}, [dependencies]);
  • Callback function: Nơi thực hiện side effect.
  • Clean-up function: Hàm trả về để dọn dẹp.
  • Dependency array: Xác định khi nào useEffect sẽ chạy lại.

3. Ví Dụ Cơ Bản: Lấy Dữ Liệu Từ API

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

const DataFetchingComponent = () => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://api.example.com/data');
      const result = await response.json();
      setData(result);
      setLoading(false);
    };

    fetchData();
  }, []); // Gọi một lần khi component mount

  if (loading) return Loading...;

  return (
    
      {data.map(item => (
        {item.name}
      ))}
    
  );
};

export default DataFetchingComponent;

4. Ví Dụ Nâng Cao: Theo Dõi Sự Thay Đổi

Giả sử bạn muốn theo dõi một state và thực hiện một tác vụ mỗi khi state đó thay đổi.

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

const CounterComponent = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `Count: ${count}`; // Cập nhật tiêu đề trang

    return () => {
      console.log(`Clean up for count: ${count}`); // Clean-up khi count thay đổi
    };
  }, [count]); // Chạy lại khi count thay đổi

  return (
    
      Count: {count}
       setCount(count + 1)}>Increase
    
  );
};

export default CounterComponent;

5. Tình Huống Sử Dụng Nâng Cao

a. Thực hiện Subscriptions

Giả sử bạn muốn đăng ký một sự kiện, ví dụ như theo dõi vị trí của chuột:

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

const MousePosition = () => {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    const handleMouseMove = (event) => {
      setPosition({ x: event.clientX, y: event.clientY });
    };

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove); // Dọn dẹp khi component unmount
    };
  }, []); // Chạy một lần khi component mount

  return (
    
      X: {position.x}, Y: {position.y}
    
  );
};

export default MousePosition;

b. Sử Dụng useEffect Với Các Dependency Phức Tạp

Bạn có thể sử dụng nhiều dependencies để kiểm soát khi nào useEffect được gọi:

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

const ComplexEffectComponent = () => {
  const [count, setCount] = useState(0);
  const [value, setValue] = useState('');

  useEffect(() => {
    const timer = setTimeout(() => {
      console.log(`Count: ${count}, Value: ${value}`);
    }, 1000);

    return () => clearTimeout(timer); // Dọn dẹp timer
  }, [count, value]); // Gọi lại khi count hoặc value thay đổi

  return (
    
       setValue(e.target.value)} 
      />
       setCount(count + 1)}>Increase Count
      Count: {count}
    
  );
};

export default ComplexEffectComponent;

6. Các Lưu Ý Quan Trọng

  • Tránh Side Effects Trong Render: Đừng thực hiện side effects trong phần render của component, vì điều này có thể dẫn đến các vấn đề về hiệu suất và lỗi không mong muốn.
  • Chỉ Sử Dụng Dependency Array Khi Cần Thiết: Nếu bạn bỏ qua dependency array, useEffect sẽ chạy lại sau mỗi lần render. Nếu bạn truyền một mảng rỗng, nó sẽ chỉ chạy một lần khi component mount.
  • Lưu Ý Đến Clean-up: Luôn nhớ dọn dẹp các tác vụ để tránh rò rỉ bộ nhớ.

7. Bài Tập Thực Hành

Hãy thử tạo một ứng dụng sử dụng useEffect để tạo một stopwatch. Mỗi giây, nó sẽ tăng một giá trị, và bạn cần sử dụng clean-up function để dừng stopwatch khi component unmount.

Nếu bạn có câu hỏi hoặc cần thêm thông tin, đừng ngần ngại hỏi nhé! Chúc các bạn học tốt!