Các thành phần lớp React


Trước React 16.8, các thành phần Class là cách duy nhất để theo dõi trạng thái và vòng đời của một thành phần React. Các thành phần chức năng được coi là "không có trạng thái".

Với việc bổ sung Hooks, các thành phần Function bây giờ gần như tương đương với các thành phần Class. Sự khác biệt rất nhỏ nên có thể bạn sẽ không bao giờ cần sử dụng thành phần Class trong React.

Mặc dù các thành phần Chức năng được ưu tiên hơn, nhưng hiện tại không có kế hoạch nào về việc loại bỏ các thành phần Lớp khỏi React.

Phần này sẽ cung cấp cho bạn một cái nhìn tổng quan về cách sử dụng các thành phần Class trong React.

Vui lòng bỏ qua phần này và thay vào đó sử dụng Thành phần chức năng.


Các thành phần React

Các thành phần là các bit mã độc lập và có thể tái sử dụng. Chúng phục vụ cùng mục đích như các hàm JavaScript, nhưng hoạt động riêng lẻ và trả về HTML thông qua một hàm render ().

Thành phần có hai loại, Thành phần lớp và Thành phần chức năng, trong chương này bạn sẽ tìm hiểu về Thành phần lớp.


Tạo một thành phần lớp

Khi tạo một thành phần React, tên của thành phần đó phải bắt đầu bằng một chữ cái viết hoa.

Thành phần phải bao gồm extends React.Componentcâu lệnh, câu lệnh này tạo ra sự kế thừa cho React.Component và cấp cho thành phần của bạn quyền truy cập vào các chức năng của React.Component.

Thành phần cũng yêu cầu một render()phương thức, phương thức này trả về HTML.

Thí dụ

Tạo một thành phần Lớp được gọi làCar

class Car extends React.Component {
  render() {
    return <h2>Hi, I am a Car!</h2>;
  }
}

Bây giờ ứng dụng React của bạn có một thành phần gọi là Car, nó trả về một <h2>phần tử.

Để sử dụng thành phần này trong ứng dụng của bạn, hãy sử dụng cú pháp tương tự như HTML thông thường: <Car />

Thí dụ

Hiển thị Carthành phần trong phần tử "gốc":

ReactDOM.render(<Car />, document.getElementById('root'));


w3schools CERTIFIED . 2022

Được chứng nhận!

Hoàn thành các mô-đun React, làm bài tập, làm bài kiểm tra và được chứng nhận w3schools !!

$ 95 GHI DANH

Cấu tạo thành phần

Nếu có một constructor()hàm trong thành phần của bạn, thì hàm này sẽ được gọi khi thành phần được khởi tạo.

Hàm khởi tạo là nơi bạn khởi tạo các thuộc tính của thành phần.

Trong React, các thuộc tính thành phần nên được giữ trong một đối tượng được gọi state.

Bạn sẽ tìm hiểu thêm về phần statesau của hướng dẫn này.

Hàm khởi tạo cũng là nơi bạn tôn trọng sự kế thừa của thành phần mẹ bằng cách bao gồm super() câu lệnh, câu lệnh này thực thi hàm tạo của thành phần mẹ và thành phần của bạn có quyền truy cập vào tất cả các chức năng của thành phần mẹ ( React.Component).

Thí dụ

Tạo một hàm khởi tạo trong thành phần Xe và thêm thuộc tính màu:

class Car extends React.Component {
  constructor() {
    super();
    this.state = {color: "red"};
  }
  render() {
    return <h2>I am a Car!</h2>;
  }
}

Sử dụng thuộc tính màu trong hàm render ():

Thí dụ

class Car extends React.Component {
  constructor() {
    super();
    this.state = {color: "red"};
  }
  render() {
    return <h2>I am a {this.state.color} Car!</h2>;
  }
}


Đạo cụ

Một cách khác để xử lý các thuộc tính thành phần là sử dụng props.

Đạo cụ giống như các đối số của hàm và bạn gửi chúng vào thành phần dưới dạng thuộc tính.

Bạn sẽ tìm hiểu thêm về propstrong chương tiếp theo.

Thí dụ

Sử dụng một thuộc tính để chuyển một màu cho thành phần Xe và sử dụng nó trong hàm render ():

class Car extends React.Component {
  render() {
    return <h2>I am a {this.props.color} Car!</h2>;
  }
}

ReactDOM.render(<Car color="red"/>, document.getElementById('root'));


Đạo cụ trong Trình tạo

Nếu thành phần của bạn có một hàm khởi tạo, thì các đạo cụ phải luôn được chuyển cho hàm tạo và cả React.Component thông qua super()phương thức.

Thí dụ

class Car extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <h2>I am a {this.props.model}!</h2>;
  }
}

ReactDOM.render(<Car model="Mustang"/>, document.getElementById('root'));


Các thành phần trong các thành phần

Chúng ta có thể tham khảo các thành phần bên trong các thành phần khác:

Thí dụ

Sử dụng thành phần Xe bên trong thành phần Nhà để xe:

class Car extends React.Component {
  render() {
    return <h2>I am a Car!</h2>;
  }
}

class Garage extends React.Component {
  render() {
    return (
      <div>
      <h1>Who lives in my Garage?</h1>
      <Car />
      </div>
    );
  }
}

ReactDOM.render(<Garage />, document.getElementById('root'));


Các thành phần trong tệp

React là tất cả về việc sử dụng lại mã và có thể thông minh nếu chèn một số thành phần của bạn trong các tệp riêng biệt.

Để làm điều đó, hãy tạo một tệp mới có .js phần mở rộng tệp và đặt mã bên trong nó:

Lưu ý rằng tệp phải bắt đầu bằng cách nhập React (như trước đây) và nó phải kết thúc bằng câu lệnh export default Car;.

Thí dụ

Đây là tệp mới, chúng tôi đặt tên cho nó Car.js:

import React from 'react';

class Car extends React.Component {
  render() {
    return <h2>Hi, I am a Car!</h2>;
  }
}

export default Car;

Để có thể sử dụng Carthành phần, bạn phải nhập tệp trong ứng dụng của mình.

Thí dụ

Bây giờ chúng tôi nhập Car.jstệp trong ứng dụng và chúng tôi có thể sử dụng Car thành phần như thể nó được tạo ở đây.

import React from 'react';
import ReactDOM from 'react-dom';
import Car from './Car.js';

ReactDOM.render(<Car />, document.getElementById('root'));


Trạng thái thành phần lớp phản ứng

Các thành phần của React Class có một stateđối tượng tích hợp sẵn.

Bạn có thể nhận thấy rằng chúng tôi đã sử dụng statetrước đó trong phần hàm tạo thành phần.

Đối statetượng là nơi bạn lưu trữ các giá trị thuộc tính thuộc về thành phần.

Khi stateđối tượng thay đổi, thành phần sẽ hiển thị lại.


Tạo đối tượng trạng thái

Đối tượng trạng thái được khởi tạo trong hàm tạo:

Thí dụ

Chỉ định stateđối tượng trong phương thức khởi tạo:

class Car extends React.Component {
  constructor(props) {
    super(props);
  this.state = {brand: "Ford"};
  }
  render() {
    return (
      <div>
        <h1>My Car</h1>
      </div>
    );
  }
}

Đối tượng trạng thái có thể chứa bao nhiêu thuộc tính tùy thích:

Thí dụ

Chỉ định tất cả các thuộc tính mà thành phần của bạn cần:

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  render() {
    return (
      <div>
        <h1>My Car</h1>
      </div>
    );
  }
}

Sử dụng stateđối tượng

Tham chiếu đến stateđối tượng ở bất kỳ đâu trong thành phần bằng cách sử dụng cú pháp:this.state.propertyname

Thí dụ:

Tham chiếu đến stateđối tượng trong render()phương thức:

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>
          It is a {this.state.color}
          {this.state.model}
          from {this.state.year}.
        </p>
      </div>
    );
  }
}


Thay đổi stateđối tượng

Để thay đổi một giá trị trong đối tượng trạng thái, hãy sử dụng this.setState()phương thức.

Khi một giá trị trong stateđối tượng thay đổi, thành phần sẽ hiển thị lại, có nghĩa là đầu ra sẽ thay đổi theo (các) giá trị mới.

Thí dụ:

Thêm một nút với một onClicksự kiện sẽ thay đổi thuộc tính màu:

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  changeColor = () => {
    this.setState({color: "blue"});
  }
  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>
          It is a {this.state.color}
          {this.state.model}
          from {this.state.year}.
        </p>
        <button
          type="button"
          onClick={this.changeColor}
        >Change color</button>
      </div>
    );
  }
}

Luôn sử dụng setState()phương thức để thay đổi đối tượng trạng thái, nó sẽ đảm bảo rằng thành phần biết rằng nó đã được cập nhật và gọi phương thức render () (và tất cả các phương thức vòng đời khác).


Vòng đời của các thành phần

Mỗi thành phần trong React có một vòng đời mà bạn có thể theo dõi và thao tác trong ba giai đoạn chính của nó.

Ba giai đoạn là: Gắn kết , Cập nhậtNgắt kết nối .


Gắn

Gắn kết có nghĩa là đưa các phần tử vào DOM.

React có bốn phương thức tích hợp được gọi, theo thứ tự này, khi gắn kết một thành phần:

  1. constructor()
  2. getDerivedStateFromProps()
  3. render()
  4. componentDidMount()

Phương render()thức này là bắt buộc và sẽ luôn được gọi, các phương thức khác là tùy chọn và sẽ được gọi nếu bạn xác định chúng.


constructor

Phương constructor()thức được gọi trước bất kỳ thứ gì khác, khi thành phần được khởi tạo và nó là nơi tự nhiên để thiết lập giá trị ban đầu statevà các giá trị ban đầu khác.

Phương constructor()thức được gọi với các propsđối số, và bạn phải luôn bắt đầu bằng cách gọi super(props)trước bất kỳ thứ gì khác, điều này sẽ khởi tạo phương thức khởi tạo của cha và cho phép thành phần kế thừa các phương thức từ cha ( React.Component) của nó.

Thí dụ:

Phương constructorthức này được gọi bởi React mỗi khi bạn tạo một thành phần:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


getDerivedStateFromProps

Phương getDerivedStateFromProps()thức này được gọi ngay trước khi hiển thị (các) phần tử trong DOM.

Đây là nơi tự nhiên để thiết lập stateđối tượng dựa trên ban đầu props.

It takes state as an argument, and returns an object with changes to the state.

The example below starts with the favorite color being "red", but the getDerivedStateFromProps() method updates the favorite color based on the favcol attribute:

Example:

The getDerivedStateFromProps method is called right before the render method:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  static getDerivedStateFromProps(props, state) {
    return {favoritecolor: props.favcol };
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));


render

The render() method is required, and is the method that actually outputs the HTML to the DOM.

Example:

A simple component with a simple render() method:

class Header extends React.Component {
  render() {
    return (
      <h1>This is the content of the Header component</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


componentDidMount

The componentDidMount() method is called after the component is rendered.

This is where you run statements that requires that the component is already placed in the DOM.

Example:

At first my favorite color is red, but give me a second, and it is yellow instead:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


Updating

The next phase in the lifecycle is when a component is updated.

A component is updated whenever there is a change in the component's state or props.

React has five built-in methods that gets called, in this order, when a component is updated:

  1. getDerivedStateFromProps()
  2. shouldComponentUpdate()
  3. render()
  4. getSnapshotBeforeUpdate()
  5. componentDidUpdate()

The render() method is required and will always be called, the others are optional and will be called if you define them.


getDerivedStateFromProps

Also at updates the getDerivedStateFromProps method is called. This is the first method that is called when a component gets updated.

This is still the natural place to set the state object based on the initial props.

The example below has a button that changes the favorite color to blue, but since the getDerivedStateFromProps() method is called, which updates the state with the color from the favcol attribute, the favorite color is still rendered as yellow:

Example:

If the component gets updated, the getDerivedStateFromProps() method is called:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  static getDerivedStateFromProps(props, state) {
    return {favoritecolor: props.favcol };
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));


shouldComponentUpdate

In the shouldComponentUpdate() method you can return a Boolean value that specifies whether React should continue with the rendering or not.

The default value is true.

The example below shows what happens when the shouldComponentUpdate() method returns false:

Example:

Stop the component from rendering at any update:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  shouldComponentUpdate() {
    return false;
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

Example:

Same example as above, but this time the shouldComponentUpdate() method returns true instead:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  shouldComponentUpdate() {
    return true;
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


render

The render() method is of course called when a component gets updated, it has to re-render the HTML to the DOM, with the new changes.

The example below has a button that changes the favorite color to blue:

Example:

Click the button to make a change in the component's state:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


getSnapshotBeforeUpdate

In the getSnapshotBeforeUpdate() method you have access to the props and state before the update, meaning that even after the update, you can check what the values were before the update.

If the getSnapshotBeforeUpdate() method is present, you should also include the componentDidUpdate() method, otherwise you will get an error.

The example below might seem complicated, but all it does is this:

When the component is mounting it is rendered with the favorite color "red".

When the component has been mounted, a timer changes the state, and after one second, the favorite color becomes "yellow".

This action triggers the update phase, and since this component has a getSnapshotBeforeUpdate() method, this method is executed, and writes a message to the empty DIV1 element.

Then the componentDidUpdate() method is executed and writes a message in the empty DIV2 element:

 

Example:

Use the getSnapshotBeforeUpdate() method to find out what the state object looked like before the update:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
    document.getElementById("div1").innerHTML =
    "Before the update, the favorite was " + prevState.favoritecolor;
  }
  componentDidUpdate() {
    document.getElementById("div2").innerHTML =
    "The updated favorite is " + this.state.favoritecolor;
  }
  render() {
    return (
      <div>
        <h1>My Favorite Color is {this.state.favoritecolor}</h1>
        <div id="div1"></div>
        <div id="div2"></div>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


componentDidUpdate

The componentDidUpdate method is called after the component is updated in the DOM.

The example below might seem complicated, but all it does is this:

When the component is mounting it is rendered with the favorite color "red".

When the component has been mounted, a timer changes the state, and the color becomes "yellow".

This action triggers the update phase, and since this component has a componentDidUpdate method, this method is executed and writes a message in the empty DIV element:

Example:

The componentDidUpdate method is called after the update has been rendered in the DOM:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  componentDidUpdate() {
    document.getElementById("mydiv").innerHTML =
    "The updated favorite is " + this.state.favoritecolor;
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <div id="mydiv"></div>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));


Unmounting

The next phase in the lifecycle is when a component is removed from the DOM, or unmounting as React likes to call it.

React has only one built-in method that gets called when a component is unmounted:

  • componentWillUnmount()

componentWillUnmount

The componentWillUnmount method is called when the component is about to be removed from the DOM.

Example:

Click the button to delete the header:

class Container extends React.Component {
  constructor(props) {
    super(props);
    this.state = {show: true};
  }
  delHeader = () => {
    this.setState({show: false});
  }
  render() {
    let myheader;
    if (this.state.show) {
      myheader = <Child />;
    };
    return (
      <div>
      {myheader}
      <button type="button" onClick={this.delHeader}>Delete Header</button>
      </div>
    );
  }
}

class Child extends React.Component {
  componentWillUnmount() {
    alert("The component named Header is about to be unmounted.");
  }
  render() {
    return (
      <h1>Hello World!</h1>
    );
  }
}

ReactDOM.render(<Container />, document.getElementById('root'));