Component Lifecycle

Component Lifecycle là gì?

  • Một cách chung chung, chúng ta có thể định nghĩa lifecycle như là: sinh ra (birth) - lớn lên (growth) - kết thúc hay là chết (death).
  • Component có thể được viết theo kiểu của vòng đời này như sau:
    • Tạo vòng đời (Mount trên DOM)
    • Cập nhật vòng đời (Updating)
    • Kết thúc vòng đời (Unmount từ DOM)
  • Quá trình trên được gọi là Component lifecycle (vòng đời của một component).

Các phương thức làm việc của component lifecycle

Lifecycle Câu lệnh Mô tả
Mount componentWillMount() Phương thức này sẽ được gọi trước khi render. Không nên sử dụng setState() tại đây vì chưa có DOM để tương tác.
componentDidMount() Phương thức này sẽ được gọi một lần duy nhất sau khi component được render xong, thường sử dụng setState() vì khi này DOM đã được tạo, thường được dùng khi muốn:
  • Get data từ server.
  • Lấy giá trị cố định của thành phần như: width, height, offset, ...
  • Khai báo setInterval cho hành động lặp lại.
  • Khai báo sự kiện như: load, scroll, resize, ...
  • ...
Updating shouldComponentUpdate() Phương thức này xác định component nên được update hay không, phương thức này có 2 giá trị:
  • true (mặc định) khi này sẽ tiếp tục thực hiện componentWillUpdate()componentDidUpdate().
  • false sẽ dừng thực hiện componentWillUpdate()componentDidUpdate().
componentWillUpdate() Phương thức này được gọi một lần duy nhất sau shouldComponentUpdate(), sử dụng trước khi re-render component.
componentDidUpdate() Chúng ta gọi phương thức này sau khi DOM đã được update xong, tại đây thường được dùng khi muốn:
  • Xử lý dữ liệu được lấy từ server.
  • Thay đổi giao diện dựa vào dữ liệu nhận được.
  • ...
Unmount componentWillUnMount() Phương thức này sẽ được gọi một lần duy nhất trước khi component được loại bỏ từ DOM, những thứ đã khai báo tại componentDidMount() cần phải được hủy. Đây cũng là phương thức kết thúc vòng đời của component.

Xem ví dụ về component lifecycle

  • Ta tạo một vòng đời (lifecycle) cho một bộ đếm (counter) tăng từ 0 cho đến 3, khi đạt đến giá trị 3 thì sẽ xóa bộ đếm để kết thúc vòng đời, ta lần lượt thực hiện các bước sau:
    • Khai báo ban đầu, render giá trị đầu tiên.
    • Cho giá trị bắt đầu tăng sau mỗi 1 giây (cập nhật State).
    • Loại bỏ component ra khỏi DOM khi giá trị đạt đến 3 (Xóa component để xem kết thúc vòng đời).

Ta xét file index.html sau:

Khai báo ban đầu

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <style>
      h2 {font-size: 50px; text-align: center;}
    </style>
  </head>
  <body>
    <div id="counter"></div>

    <script type="text/babel">
      class Counter extends React.Component {
        constructor(props) {
          super(props);
          this.state = { count: 1 };
        };

        render() {
          return (
            <h2>{this.state.count}</h2>
          );
          console.log('count = ' + this.state.count);
        };
      };

      ReactDOM.render(
        <Counter />,
        document.getElementById('counter')
      );
    </script>
  </body>
</html>
  • Khi xem Console (Nhấn F12) ta sẽ thấy kết quả output sau:
count = 1

Cho giá trị bắt đầu tăng sau mỗi 1 giây

  • Tạo function count để cập nhật giá trị với setState.
  • Cần setInterval để giá trị tự động cập nhật function count.
  • Do component đã được render xong, nên setInterval ta đặt bên trong componentDidMount (như đã nói ở table bên trên).
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 1 };
  };

  countFnc = () => {
    this.setState({
      count: this.state.count + 1
    });
  };

  componentDidMount() {
    setInterval(() => this.countFnc(), 1000);
    console.log("componentDidMount");
  };

  render() {
    console.log('count = ' + this.state.count);
    return (
      <h2>{this.state.count}</h2>
    );
  };
};

ReactDOM.render(
  <Counter />,
  document.getElementById('counter')
);

Kết quả Output

count = 1
componentDidMount
count = 2
count = 3
count = 4
...
  • Giá trị sẽ được tăng 1 đơn vị trên giây, Do chưa có điều kiện kết thúc nên giá trị sẽ được tăng vô hạn.

Loại component ra khỏi DOM khi giá trị đạt đến 3

  • Ta tận dụng việc gọi một lần duy nhất của phương thức componentDidUpdate để loại bỏ component ra khỏi DOM khi giá trị đạt đến 3.
  • Sử dụng ReactDOM.unmountComponentAtNode() để loại bỏ component ra khỏi DOM.
  • Sau khi Component đã được loại bỏ khỏi DOM, ta cần sử dụng phương thức componentWillUnmount() để xóa interval đã đăng ký từ componentDidMount(), nếu không sẽ báo lỗi vì vòng đời không được kết thúc.
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 1 };
  };

  countFnc = () => {
    this.setState({
      count: this.state.count + 1
    });
  };

  componentDidMount() {
    this.counterID = setInterval(() => this.countFnc(), 1000);
    console.log("componentDidMount");
  };

  componentDidUpdate(prevProps, prevState) {
    console.log("componentDidUpdate");
    if (this.state.count === 3) {
      ReactDOM.unmountComponentAtNode(document.getElementById('counter'));
    }
  };

  componentWillUnmount() {
    console.log("componentWillUnmount");
    clearInterval(this.counterID);
  };

  render() {
    console.log('count = ' + this.state.count);
    return (
      <h2>{this.state.count}</h2>
    );
  };
};

ReactDOM.render(
  <Counter />,
  document.getElementById('counter')
);

Kết quả Output

count = 1
componentDidMount
count = 2
componentDidUpdate
count = 3
componentDidUpdate
componentWillUnmount
  • Ta thấy kết quả đã dừng lại ở 3, khi này sau khi gọi phương thức componentWillUnmount() thì vòng đời đã kết thúc.
  • Bên trên là một ví dụ đơn giản về cách tạo vòng đời component, trong thực tế tùy vào mục đích sử dụng mà ta có thể điều chỉnh vòng đời dừng tại đâu cho phù hợp, ví dụ nếu tạo một đồng hồ điện tử, thì ta sẽ không cho vòng đời kết thúc, khi đó sẽ không cần sử dụng componentWillUnmount().