+7

useEffect vs useLayoutEffect trong React: Kinh nghiệm thực tế

image.png

Giới thiệu 🌟

Kể từ khi React 16.8 ra đời với Hooks, cách viết component đã thay đổi đáng kể. Trong số các hooks mới, useEffect và useLayoutEffect đóng vai trò quan trọng trong việc xử lý side effects. Thoạt nhìn chúng có vẻ giống nhau, nhưng thực tế lại có những khác biệt đáng kể.

Trong bài viết này, mình sẽ chia sẻ kinh nghiệm thực tế về việc sử dụng useEffect và useLayoutEffect, giúp các bạn hiểu rõ khi nào nên dùng cái nào cho phù hợp. Cùng đi sâu tìm hiểu hai hooks này nhé!

useEffect là gì? 🔍

useEffect là một hook trong React cho phép thực hiện các side effects trong functional component. Side effects ở đây có thể hiểu là các thao tác ảnh hưởng đến bên ngoài component, ví dụ như gọi API, thao tác DOM, đăng ký sự kiện, v.v.

Lưu ý là 99% trường hợp, useEffect là hook bạn cần dùng.

Cách sử dụng useEffect:

useEffect(() => {
  // Code xử lý side effect ở đây
}, [dependencies]);

Tham số thứ hai [dependencies] là một mảng các dependencies. React sẽ chỉ chạy lại effect khi một trong các dependencies thay đổi. Nếu truyền một mảng rỗng [], effect sẽ chỉ chạy một lần sau lần render đầu tiên, tương tự componentDidMount trong class component.

useLayoutEffect là gì? 🤔

useLayoutEffect cũng tương tự như useEffect, nhưng có một điểm khác biệt quan trọng về thời điểm thực thi. Nó được sử dụng cho các thao tác cần đồng bộ hóa với DOM, như điều chỉnh layout trước khi trình duyệt vẽ lại màn hình.

Khi nào nên dùng useLayoutEffect:

Sử dụng useLayoutEffect khi bạn cần thực hiện các thay đổi DOM trước khi trình duyệt cập nhật giao diện. Điều này giúp tránh các hiện tượng nhấp nháy hoặc giật lag khi thao tác với DOM.

useLayoutEffect(() => {
  // Code tương tác với DOM ở đây
}, [dependencies]);

Tương tự useEffect, nó cũng nhận một mảng dependencies làm tham số thứ hai.

So sánh useEffect và useLayoutEffect trong thực tế ⚖️

Để hiểu rõ hơn sự khác biệt, hãy xem xét một ví dụ cụ thể:

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

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

  useEffect(() => {
    console.log('useEffect chạy sau khi render và paint');
    // Giả lập một tác vụ nặng
    let i = 0;
    while (i < 1000000000) i++;
    setCount(prevCount => prevCount + 1);
  }, []);

  useLayoutEffect(() => {
    console.log('useLayoutEffect chạy trước khi paint');
    // Thực hiện các thay đổi DOM ở đây
    document.getElementById('output').style.color = 'red';
  }, [count]);

  return (
    <div>
      <h1 id="output">Số lần render: {count}</h1>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>
        Tăng
      </button>
    </div>
  );
};

export default ExampleComponent;

Trong ví dụ này:

  • useEffect sẽ chạy sau khi component đã được render và paint lên màn hình. Nó thực hiện một tác vụ nặng (giả lập) và sau đó cập nhật state, gây ra re-render.
  • useLayoutEffect chạy ngay sau khi tất cả các DOM mutations đã hoàn tất, nhưng trước khi trình duyệt paint. Nó thay đổi màu chữ của phần tử output.

Khi chạy component này, bạn sẽ thấy:

  1. Màu chữ đỏ xuất hiện ngay lập tức, không có hiện tượng nhấp nháy.
  2. Giá trị count tăng lên sau một khoảng thời gian ngắn (do tác vụ nặng trong useEffect).

Lưu ý khi sử dụng 📝

  1. Sử dụng useEffect cho hầu hết các trường hợp, đặc biệt là các tác vụ không yêu cầu đồng bộ với DOM.

  2. Chỉ sử dụng useLayoutEffect khi cần thao tác DOM và muốn các thay đổi được áp dụng ngay trước khi trình duyệt paint, tránh hiện tượng nhấp nháy.

  3. useLayoutEffect chạy đồng bộ, có thể ảnh hưởng đến hiệu suất nếu sử dụng không đúng cách. Hãy cân nhắc kỹ trước khi dùng.

  4. Trong môi trường server-side rendering, useLayoutEffect sẽ gây ra cảnh báo. Trong trường hợp này, hãy sử dụng useEffect hoặc chuyển logic vào useEffect với một flag để chỉ chạy ở client-side.

Cuối cùng 🎯

Hiểu được sự khác biệt giữa useEffect và useLayoutEffect sẽ giúp bạn tối ưu hóa hiệu suất và trải nghiệm người dùng trong ứng dụng React. Hãy nhớ rằng, trong hầu hết các trường hợp, useEffect là lựa chọn an toàn và hiệu quả. Chỉ sử dụng useLayoutEffect khi bạn thực sự cần đồng bộ hóa với DOM để tránh các vấn đề về hiển thị.

Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về hai hooks quan trọng này trong React. Hãy áp dụng kiến thức này vào dự án của bạn và đừng ngần ngại thử nghiệm để tìm ra cách sử dụng tối ưu nhất nhé!

Nếu bạn có bất kỳ câu hỏi hoặc chia sẻ kinh nghiệm gì, đừng ngại comment bên dưới. Chào thân ái và quyết thắng 💻🚀


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.