Sử dụng Effect Hook - React - Part 1

Sử dụng Effect Hook - React - Part 1
useEffect React Hook

Hooks là một tính năng mới được thêm vào React 16.8. Nó cho phép bạn có thể sử dụng state và các chứ năng khác của React mà không cần khởi tạo Class, điều đó có nghĩa là có thể sử dụng state trong functional component.

Effect Hook cho phép thực hiện Side Effect bên trong các function component

Để có cái nhìn tổng quan về React Hooks và hiểu thêm về sự khác biệt của Hooks ( Function Component) và Class Component thì các bạn đọc thêm bài này nha https://blog.haposoft.com/cai-nhin-tong-quan-ve-react-hooks/

1. Side Effect là gì ? Và chúng có bao nhiêu loại ?

Side Effects: là chương trình phần mềm khi có tác động xảy ra, dẫn đến việc dữ liệu bị thay đổi. Ví dụ Side Effect:

  • Gọi API lấy dử liệu
  • Tương tác với DOM
  • Subscriptions
  • setTimeOut, setInterval

Thằng React chia Side Effect làm 2 nhóm:

  1. Effect không cần cleanup : Gọi API , tương tác với DOM
  2. Effect cần cleanup : subscriptions, setTimeOut, setInterval

2. Hook useEffect() là gì?

  • Nếu bạn đã quen thuộc với các phương thức vòng đời của lớp React, bạn có thể nghĩ đến useEffect Hook khi kết hợp componentDidMount, componentDidUpdate và componentWillUnmount.
  • Mục đích useEffect để quản lý vòng đời của của một component.
  • Sử dụng cho Side Effect.
  • Mỗi hook có 2 thành phần là side effect và clean up (optional)
  • Được thực thi sau mỗi lần render
  • Effect cleanup function luôn được gọi trước khi run effect lần tiếp theo hoặc trước khi component unmounted

Cú pháp

useEffect(callback, dependencies) {}

// callback : Side effect của bạn, luôn được gọi sau khi component mounted
// dependencies : Chỉ thực hiện lệnh gọi lại nếu một trong các phần phụ thuộc của bạn thay đổi

Cách useEffect chạy:

Lần render đầu tiên:
MOUNTING

  • rendering (render phần component)
  • run useEffect() (Lưu ý là nó chỉ run phần side effect chứ chưa run phần cleanup nhé)

Đến lần render tiếp theo.
UPDATING

  • rendering (lại render phần component trước)
  • run useEffect() cleanup nếu dependencies thay đổi (Lúc này nó sẽ cleanup cái side effect chạy lần trước ở mounting nhé)
  • run useEffect() nếu dependencies thay đổi. (Đoạn này nó sẽ chạy side effect lần 2 nhé)

Bước cuối cùng nó sẽ chạy unmount để nó đảm bảo đã cleanup hết trước khi unmounted
UNMOUNTING

  • run useEffect() cleanup

3. Lưu ý khi dùng useEffect()

Có 3 cách dùng useEffect với điều kiện:

Cách 1 : useEffect(callback)

function Example() {

  useEffect(() => {
       return function cleanup() {
          // cleanup
        };
  });

  return ();
}

Nếu không khai báo dependencies đồng nghĩa với việc nó luôn luôn được thực hiện .

  • Luôn gọi callback function mỗi khi component re-render
  • Thời điểm chạy: Hàm callback chạy sau khi component thêm element vào DOM

Cách 2 : useEffect(callback, [])

function Example() {

  useEffect(() => {
       return function cleanup() {
          // cleanup
        };
  }, []);

  return ();
}

Nếu khai báo dependencies và dependencies là 1 mảng rỗng có nghĩa nó sẽ chạy đúng 1 lần sau khi component mounted.

Cách 3 : useEffect(callback, [deps])

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

  useEffect(() => {

        return function cleanup() {
          // cleanup
        };
  }, [count]);

  return ();
}

Nó cần sẽ chạy lần đầu sau khi render. Và những lần sau nó có render hay không thì nó sẽ phụ thuộc vào thằng count.
Hiểu nôm na là thằng useEffect sẽ kiểm tra thằng deps trước và sau khi render có khác nhau hay không. Nếu khác nhau nó sẽ đến thằng callback này.

4. Lưu ý khi dùng useEffect()

  • Side effect là gì ? Có bao nhiêu loại ?
  • Có thể kèm điều kiện để thực thi useEffect()
  • Có thể dùng nhiều useEffect()
  • Tư duy về side Effects khi dùng useEffect() hook thay vì lifeCycle (Đừng tư duy theo kiểu từ class component viết như nào rùi conver qua hook nhé. Suy nghĩ vậy là sai lầm).

Tài liệu tham khảo

https://toidicodedao.com/2018/09/11/su-khac-biet-giua-server-side-rendering-va-client-side-rendering/
https://viblo.asia/p/server-side-rendering-vs-client-side-rendering-RQqKLz30l7z