[React] Cách sử dụng useEffect() thay thế lifecycle method

0

Nằm trong series học React, trong  bài viết này, chúng ta sẽ cùng nhau tìm hiểu cặn kẽ cách sử dụng useEffect Hook.

Về cơ bản, useEffect Hook  được dùng mục đích để quản lý vòng đời của một component. Chúng ta sử dụng hook này trong các function component thay thế các lifecycle trong class component (cơ bản là giống nhau).

Do useEffect() có cách hoạt động tương đối giống với các hàm trong lifecycle của component, nên mình sẽ viết bài này cũng theo hướng cố gắng đối chiếu với lifecycle.

Cú pháp useEffect()

Cú pháp của useEffect() cơ bản như sau:

#syntax
useEffect(effectFunction, arrayDependencies)

Trong đó:

  • effectFunction: gọi là side-effect function, thường được để bạn thực hiện logic chương trình khi useEffect được gọi.
  • arrayDependencies: mảng phụ thuộc, cơ bản là để bạn xác định khi nào thì hàm side-effect được gọi.

React useEffect Hook: luôn luôn gọi

Hãy cùng xem xét ví dụ đầu tiên về cách sử dụng useEffect Hook của React. Trong đó, chúng ta truyền vào useEffect một hàm – hay gọi là side-effect function.

const Toggler = ({ toggle, onToggle }) => {
  React.useEffect(() => {
    console.log('I run on every render: mount + update.');
  });
 
  return (
    <div>
      <button type="button" onClick={onToggle}>
        Toggle
      </button>
 
      {toggle && <div>Hello React</div>}
    </div>
  );
};

Đây là cách sử dụng đơn giản nhất. Trong đó, chúng ta chỉ truyền một đối số – là một hàm số. Hàm này sẽ được gọi mọi lúc – bất cứ khi nào component được render để hiển thị (bao gồm cả lúc update hoặc tạo mới component).

React useEffect Hook: chỉ gọi lúc component được mount xong

Nếu bạn chỉ muốn chạy useEffect Hook duy nhất lúc component được mount (lần đầu tiên component hiển thị), bạn chỉ cần truyền vào mảng rỗng vào đối số thứ 2 của useEffect

const Toggler = ({ toggle, onToggle }) => {
  React.useEffect(() => {
    console.log('I run only on the first render: mount.');
  }, []);
 
  return (
    <div>
      <button type="button" onClick={onToggle}>
        Toggle
      </button>
 
      {toggle && <div>Hello React</div>}
    </div>
  );
};

Tham số thứ hai – ở đây chúng ta truyền vào là mảng rỗng – gọi là dependency array. Nếu dependency array là rỗng, thì hàm side-effect trong đối số thứ nhất không có dependencies. Điều này có nghĩa là nó chỉ chạy duy nhất lần đầu tiên khi component hiển thị.

React useEffect Hook: gọi khi update giá trị điều kiện

Trong trường hợp dependency array  không phải là mảng rỗng thì sao?

Nếu mảng này có phần tử, mỗi khi giá trị của phần tử thay đổi, hàm side-effect sẽ được gọi.

const Toggler = ({ toggle, onToggle }) => {
  React.useEffect(() => {
    console.log('I run only if toggle changes (and on mount).');
  }, [toggle]);
 
  return (
    <div>
      <button type="button" onClick={onToggle}>
        Toggle
      </button>
 
      {toggle && <div>Hello React</div>}
    </div>
  );
};

Như ví dụ trên, hàm side-effect để  in ra màn hình console.log("...") sẽ được gọi khi biến toggle thay đổi giá trị. Tuy nhiên, bạn cũng cần phải lưu ý rằng, hàm side-effect cũng được gọi khi lần đầu tiên component hiển thị (khi component mount).

Ngoài ra, một điểm cũng cần lưu tâm, dependency array dù sao cũng là một mảng nên nó có thể chứa nhiều hơn một phần tử. Do vậy, bạn có thể thêm nhiều biến hơn vào mảng này, tùy vào mục đích của bạn.

const Toggler = ({ toggle, onToggle }) => {
  const [title, setTitle] = React.useState('Hello React');
 
  React.useEffect(() => {
    console.log('I run if toggle or title change (and on mount).');
  }, [toggle, title]);
 
  const handleChange = (event) => {
    setTitle(event.target.value);
  };
 
  return (
    <div>
      <input type="text" value={title} onChange={handleChange} />
 
      <button type="button" onClick={onToggle}>
        Toggle
      </button>
 
      {toggle && <div>{title}</div>}
    </div>
  );
};

React useEffect Hook: UnMount

Bạn đã biết cách sử dụng useEffect() khi một component mount xong. Vậy khi component chuẩn bị remove khỏi DOM thì sao?

Cùng xem ví dụ sau nhé:

import * as React from 'react';
 
const App = () => {
  const [timer, setTimer] = React.useState(0);
 
  React.useEffect(() => {
    const interval = setInterval(
      () => setTimer((currentTimer) => currentTimer + 1),
      1000
    );
 
    return () => clearInterval(interval);
  }, []);
 
  return <div>{timer}</div>;
};
 
export default App;

Thì thực tế thì useEffect cho phép chúng ta return  một function, function này sẽ thực thi trước khi mà component đó được unmounted.

Đối chiếu Component lifecycle với useEffect Hook

Sau khi chúng ta đã tìm hiểu xong những cách dùng cơ bản của useEffect Hook,  hẳn bạn sẽ có cảm giác liên tưởng tới lifecycle của component đúng không?

Thực ra đúng là có sự liên quan nhè nhẹ ở đây.

Vòng đời của Component trong ứng dụng React,  bạn vẫn còn nhớ những hàm như:

  • componentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()
  • v…

Đối chiếu với phần trên của bài viết, chúng ta sẽ có bản đối chiếu tương ứng như sau:

1. ComponentDidMount()

Tương ứng với lifecycle này là cách viết sau:

useEffect(() => {
    // Bạn viết code xử lý logic tại đây
}, []);

2. ComponentDidUpdate()

Tương ứng với lifecycle này là cách viết sau:

useEffect(() => {
    // Bạn viết code xử lý logic tại đây
});

3. ComponentWillUnMount()

Tương ứng là:

useEffect(() => {  
    // hàm được trả về sẽ được gọi khi component unmount 
    return () => {
      // Bạn viết code xử lý logic tại đây khi component unmount.
    }
}, [])

Cám ơn đã đọc bài viết

👍 Đọc thêm về React:

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo