Vòng đời của Component trong ReactJs với ES6

Có thể nói, khái niệm component trong React là một trong những thành phần quan trọng nhất của React. Do vậy, việc hiểu rõ vòng đời của component sẽ giúp cho bạn hiểu rõ hơn về React.

Nội dung chính

Chú ý: Cập nhật React phiên bản 16.9

Từ 8/8/2019, phiên bản 16.9 ra đời đánh dấu sự kết thúc danh sách các phương thức component. Vì vậy các nội dung bên dưới chỉ đọc để tham khảo mà không nên sử dụng từ React 16.9. Bài viết về các phương thức thay thế sẽ được nói đến trong bài “Vòng đời của các component từ React 16.9”.

Bạn hãy đăng ký nhận bài ở cột bên phải, bạn sẽ được thông báo bài viết mới về “Vòng đời của các component từ React 16.9”.

Tài liệu về component không sử dụng ES6

Bạn có thể tham khảo tài liệu chính thức (Không ES6) tại đây:

http://facebook.github.io/react/docs/component-specs.html

Đây là một trang rất rõ ràng, chi tiết khác (Không ES6)

http://busypeoples.github.io/post/react-component-lifecycle/

Tuy nhiên, các tài liệu trên không viết cho ES6, nên bài viết này sẽ viết lại với code thuộc ES6, về cơ bản chỉ khác ở phần khởi tạo props và state

Trong bài viết sử dụng ES6/ES2015, nếu bạn chưa quen thì hạy đọc thêm bài ES6/ES2015 là gì

Danh sách các hàm/phương thức của component

Danh sách các method của một component, bạn vui lòng đọc kỹ trong code có những dòng chú thích giải thích rõ về chức năng của hàm. Việc nắm hết các phương thức sau là điều kiện tiên quyết để hiểu vòng đời của component hoạt động như thế nào.

import React, {Component, PropTypes} from 'react';

class User extends Component {
  constructor(props){
    super(props)
    // Hàm này Thực hiện việc thiết lập state cho component
    // Việc sử dụng super(props) là để có thể sử dụng this.props trong phạm vi hàm constructor này
  }
  
  componentWillMount() {
    // Thực hiện một số tác vụ, hàm này chỉ thực hiện 1 lần duy nhất
    
  }
  componentDidMount() {
    // Thực hiện một số tác vụ, hàm này chỉ thực hiện 1 lần duy nhất
    // Hàm này rất hữu dụng khi bạn làm việc thêm với Map, bởi vì map chỉ render được 
    // khi có node (id) trong DOM  
    // Nói tóm lại, hàm này được gọi để thông báo component đã tồn tại trên DOM, 
    // từ đó các thao tác trên DOM sẽ có thể thực hiện bình thường đối với component này
  }
  componentWillUnmount() {
    // Hàm này thực hiện một lần duy nhất, khi component sẽ unmount
    // Hàm này hữu dụng khi bạn cần xoá các timer không còn sử dụng
  }
  componentWillReceiveProps(nextProps) {
    // Hàm này thực hiện liên tục mỗi khi props thay đổi
    // (1) Sử dụng để thay đổi trạng thái (state) của component phụ thuộc props
    // (2) Sử dụng các kết quả, khởi tạo biến có tính chất async. Ví dụ: Khởi tạo Google Map Api, đây là quá trình async,
    // do vậy, bạn không thể biết được khi nào khởi tạo xong, thì khi khởi tạo xong có thể truyền xuống component thông qua
    // props, và từ đó bạn có thể khởi tạo các dịch vụ khác.
    // Code mẫu:
    //# if(nextProps.mapLoaded){ //props.mapLoaded khởi tạo false
    //#     let googleMaps = this.props.googleMaps ||
    //#         (window.google && // eslint-disable-line no-extra-parens
    //#         window.google.maps) ||
    //#         this.googleMaps;

    //#     if (!googleMaps) {
    //#         console.error(// eslint-disable-line no-console
    //#          'Google map api was not found in the page.');
    //#         return;
    //#     }
    //#     this.googleMaps = googleMaps;

    //#     this.autocompleteService = new googleMaps.places.AutocompleteService();
    //#     this.geocoder = new googleMaps.Geocoder();
    //# } 
  }
  shouldComponentUpdate(nextProps, nextState) {
    // Hàm này thực hiện khi state và props thay đổi
    // Hàm này sẽ trả về kết quả true/false, bạn sẽ cần sử dụng đến hàm này để xử lý xem có cần update component không
  }
  
  componentWillUpdate(nextProps, nextState) {
    // Hàm này thực hiện dựa vào kết quả của hàm trên (shouldComponentUpdate)
    // Nếu hàm trên trả về false, thì React sẽ không gọi hàm này
  }  
  componentDidUpdate(prevProps, prevState) {
    // Hàm này thực hiện sau khi component được render lại, từ kết quả của componentWillUpdate
  }
  
  render() {
    return (
      <div>
        // thực hiện việc render
      </div>
    );
  }
}

User.propTypes = {
  //Khai báo kiểu biến cho props
};
User.defaultProps = {
  //Khai báo giá trị mặc định cho props
}
export default User;

Như vậy, class phía trên đã liệt kê toàn bộ phương thức của Component, tiếp theo chúng ta sẽ xem xét các sự kiện tương tác ảnh hưởng đến Component như thế nào.

Vòng đời của component

Khởi tạo Component

Lần lượt các hành động sau để khởi tạo component:

  • Khởi tạo Class (đã thừa kế từ class Component của React)
  • Khởi tạo giá trị mặc định cho Props (defaultProps)
  • Khởi tạo giá trị mặc định cho State (trong hàm constuctor)
  • Gọi hàm componentWillMount()
  • Gọi hàm render()
  • Gọi hàm componentDidMount()

Khi State thay đổi

  • Cập nhật giá trị cho state
  • Gọi hàm shouldComponentUpdate()
  • Gọi hàm componentWillUpdate() – với điều kiện hàm trên return true
  • Gọi hàm render()
  • Gọi hàm componentDidUpdate()

Khi Props thay đổi

  • Cập nhật giá trị cho props
  • Gọi hàm componentWillReceiveProps()
  • Gọi hàm shouldComponentUpdate()
  • Gọi hàm componentWillUpdate() – với điều kiện hàm trên return true
  • Gọi hàm render()
  • Gọi hàm componetDidUpdate()

Khi Unmount component

  • Gọi hàm componentWillUnmount()

Nói thêm về setState

Trong React, bạn chỉ khởi tạo giá trị this.state một lần duy nhất, sau khi khởi tạo xong, nếu bạn muốn cập nhật this.state, bạn phải dùng hàm this.setState.

Khi sử dụng this.setState, chính là kích hoạt danh sách các phương thức thuộc vòng đời của component (shouldComponentUpdate, componentWillUpdate, render, componentDidUpdate). Và cũng luôn nhớ rằng, this.setState là hàm async, nên truy cập this.state ngay sau khi setState sẽ không nhận được giá trị mới của this.state.

Hãy thử xem đoạn code sau:

componentWillReceiveProps(nextProps){
  this.setState(nextProps)
  console.log(this.state) //=> in ra giá trị cũ của state, không được cập nhật nextProps
}

Để khắc phục khi bạn muốn thực hiện thêm 1 hành động nào đó như lưu log, tracking, thông báo… thì bạn sử dụng hàm callback như sau:

componentWillReceiveProps(nextProps){
  this.setState(nextProps, ()=>{
    this.updateDatabase(this.state)
  })
}

Ở đoạn code trên mình lồng trong componentWillReceiveProps chỉ là ví dụ thôi nhé, bạn có thể sử dụng cách viết callback sau khi setState ở bất cứ đâu trong component ngoại trừ hàm render()

Kết

Khi mới bước chân vào hệ sinh thái React, bạn cũng sẽ như mình lúng túng với Flux, Redux…Nó là những khái niệm rất khó nuốt, và càng khó nuốt hơn khi bạn chưa nắm rõ vòng đời của component trong React như thế nào.

Mình nhắc lại là việc hiểu rõ nó rất quan trọng, hi vọng qua bài viết này sẽ giúp bạn đạt được điều đó. Với những ứng dụng không quá phức tạp về phía người dùng, sự liên kết trao đổi dữ liệu giữa các component không cùng cha-con thì không cần phải quan tâm đến Flux/Redux.

Series Navigation<< Hướng dẫn sử dụng Redux hiệu quả trong ứng dụng React

Comments


Posted

in

, ,

by

Tags:

Comments

6 bình luận cho “Vòng đời của Component trong ReactJs với ES6”

  1. Ảnh đại diện nguyễn Anh đông
    nguyễn Anh đông

    DANH SÁCH CÁC HÀM/PHƯƠNG THỨC CỦA COMPOPENT. Từ COMPOPENT –> Component

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *