0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Sử Dụng useEffect Hiệu Quả Trong React: Ngừng Lạm Dụng Ngay!

Đăng vào 7 tháng trước

• 5 phút đọc

Hướng Dẫn Sử Dụng useEffect Hiệu Quả Trong React

Giới thiệu

Trong thế giới phát triển ứng dụng web, React đã trở thành một trong những thư viện phổ biến nhất. Tuy nhiên, một trong những khía cạnh khó khăn nhất mà các lập trình viên phải đối mặt là cách sử dụng hook useEffect một cách hiệu quả. Nhiều lập trình viên, thậm chí cả AI, thường lạm dụng useEffect, dẫn đến các vấn đề khó khăn trong việc quản lý trạng thái và hiệu suất ứng dụng. Trong bài viết này, chúng ta sẽ khám phá cách sử dụng useEffect một cách đúng đắn và hiệu quả.

Tóm Tắt Về Lifecycle Hooks

Trước khi React giới thiệu hooks, các component được viết dưới dạng class với các phương thức như componentDidMount, componentDidUpdate, và componentWillUnmount. Mô hình này có nhiều hạn chế, chẳng hạn như việc logic thường bị phân tán giữa các lifecycle hooks khác nhau. Điều này làm cho việc quản lý trạng thái trở nên khó khăn hơn.

React Hooks và useEffect

Kể từ phiên bản 16.8, React đã giới thiệu một loạt hooks, trong đó có useEffect. Hooks cho phép lập trình viên xử lý các tác động bên ngoài mà không cần phải sử dụng các lifecycle methods. useEffect cho phép bạn thực hiện các hoạt động như gọi API, thiết lập các sự kiện lắng nghe từ DOM, và nhiều hơn nữa. Cách sử dụng useEffect là truyền vào một hàm thực hiện tác động và một mảng các biến phụ thuộc.

Các Trường Hợp Sử Dụng useEffect

useEffect nên được sử dụng cho những trường hợp như:

  • Gọi API (fetch/axios/WebSockets)
  • Thiết lập Timer (setTimeout, setInterval)
  • Sử dụng các API của trình duyệt (navigator, localStorage)

Quy tắc vàng: "Nếu không có hệ thống bên ngoài nào liên quan, bạn thường không cần sử dụng useEffect."

Tại Sao useEffect Lại Khó Hiểu?

Nhiều lập trình viên đã hiểu sai về useEffect, sử dụng nó để chạy mã trong quá trình mount hoặc đồng bộ hóa trạng thái giữa các component. Điều này xảy ra do thiếu thông tin rõ ràng trong tài liệu hướng dẫn. Hiện tại, tài liệu mới đã cung cấp thông tin rõ ràng hơn nhưng vẫn có nhiều người bỏ qua.

Suy Nghĩ Theo Tác Động

Nhiều lập trình viên nghĩ về useEffect từ góc độ lifecycle của component thay vì từ góc độ của tác động. Ví dụ:

javascript Copy
useEffect(() => {
  const connection = createConnection(serverUrl, roomId);
  connection.connect();
  return () => {
    connection.disconnect();
  };
}, [roomId]);

Thay vì nghĩ rằng "kết nối khi mount và ngắt kết nối khi unmount", hãy nghĩ rằng "tôi muốn kết nối với một phòng chat từ component của mình".

Những Điều Nên Làm Khi Sử Dụng useEffect

Ví Dụ Về Sử Dụng Đúng

  1. Gọi dữ liệu:

    javascript Copy
    useEffect(() => {
      fetch('/api/user')
        .then(res => res.json())
        .then(data => setUser(data));
    }, []);
  2. Đồng bộ hóa trạng thái với localStorage:

    javascript Copy
    useEffect(() => {
      localStorage.setItem('theme', theme);
    }, [theme]);
  3. Lắng nghe sự kiện DOM:

    javascript Copy
    useEffect(() => {
      const handleScroll = () => setScrollY(window.scrollY);
      window.addEventListener('scroll', handleScroll);
      return () => window.removeEventListener('scroll', handleScroll);
    }, []);

Khi Nào Bạn Cần Sử Dụng useEffect

  • Gọi dữ liệu (với các lưu ý quan trọng).
  • Đồng bộ hóa trạng thái với hệ thống bên ngoài.
  • Đăng ký lắng nghe dữ liệu từ các API của trình duyệt.

Những Điều Không Nên Làm Khi Sử Dụng useEffect

Ví Dụ Về Việc Sử Dụng Sai

  1. Truyền đổi dữ liệu để hiển thị:

    javascript Copy
    function Form() {
      const [firstName, setFirstName] = useState('Morty');
      const [lastName, setLastName] = useState('Smith');
      const [fullName, setFullName] = useState('');
    
      useEffect(() => {
        setFullName(firstName + ' ' + lastName);
      }, [firstName, lastName]);
    
      return <span>{fullName}</span>;
    }

    Thay vào đó, hãy tính toán fullName ngay trong quá trình render.

  2. Lưu cache các phép tính tốn kém:

    javascript Copy
    function TodoList({ todos }) {
      const [searchTerm, setSearchTerm] = useState('');
      const [matchingTodos, setMatchingTodos] = useState(todos);
    
      useEffect(() => {
        setMatchingTodos(todos.filter(todo => todo.title.includes(searchTerm)));
      }, [searchTerm]);
    }

    Thay vào đó, hãy tính toán matchingTodos trong quá trình render và sử dụng useMemo nếu cần.

  3. Đặt lại trạng thái khi thay đổi prop:

    javascript Copy
    useEffect(() => {
      setSearchTerm('');
    }, [todos]);

    Thay vào đó, sử dụng prop key để cho React biết rằng các todos đã thay đổi.

Khi Nào Bạn Không Cần useEffect

  1. Chuyển đổi dữ liệu để hiển thị.
  2. Lưu trữ cache các phép tính tốn kém.
  3. Điều chỉnh/Đặt lại trạng thái khi thay đổi prop.
  4. Xử lý sự kiện người dùng.
  5. Đồng bộ hóa trạng thái giữa các component cha và con.

Alternatives cho useEffect: useSyncExternalStore

Nếu bạn có hook tùy chỉnh đồng bộ với một kho lưu trữ bên ngoài, bạn có thể sử dụng useSyncExternalStore thay vì useEffect. Điều này giúp đơn giản hóa mã của bạn và cải thiện hiệu suất.

Tương Lai Của useEffect

Nhóm phát triển React đang xem xét việc sử dụng Compiler mới của React như một giải pháp để tự động phát hiện các phụ thuộc cho bạn. Điều này sẽ giúp lập trình viên nghĩ về mã trong useEffect như một tác động thực sự thay vì chỉ là "nếu phụ thuộc này thay đổi, hãy chạy hàm này".

Kết Luận

Việc loại bỏ các tác động không cần thiết sẽ làm cho mã dễ theo dõi, dễ gỡ lỗi, nhanh hơn và ít lỗi hơn. Nếu chúng ta sử dụng useEffect một cách chính xác, AI cũng sẽ sử dụng nó đúng cách. Hy vọng rằng sau khi đọc bài viết này, bạn sẽ biết khi nào nên và không nên sử dụng useEffect.

Đọc thêm về useSyncExternalStore trong bài viết của tôi: Xây Dựng Thư Viện Quản Lý Trạng Thái React Trong Dưới 40 Dòng Mã

Xem thêm "Bạn Có Thể Không Cần Một Tác Động" trong tài liệu của React để biết thêm thông tin chi tiết và ví dụ.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào