ReactJS: Lifecycle trong ReactJS -get Derived State From Props là gì?

Một trong những phần quan trọng khi phát triển một React Component là hiểu được những lifecycles. Hiểu được khi nào Component khởi tạo(constructor), component đã được build thành DOM(componentDidMount), component đã được cập nhật state(componentDidUpdate), khi nào component bị huỷ bỏ(componentWillUnmount),… Bạn có thể tham khảo toàn bộ sơ đồ tại đây.

Và có một phương thức static khiến nhiều người hiểu lầm và thảo luận nhiều về nó là getDerivedStateFromProps. Vậy tại sao React lại tạo ra getDerivedStateFromProps? Hiểu nghĩa câu này là: “nhận những state mới mà nó được tạo ra bởi những props”. “Derived” có nghĩa là đến từ và được tạo ra bởi một điều gì đó, mà ở đây là props.

Một component có 3 giai đoạn là: khởi tạo, cập nhật và phá huỷ nó. Thông thường ở gian đoạn cập nhật mới thật sự nảy ra nhiều câu chuyện đau đầu. Một component có hàm render. Vậy khi nào hàm render được chạy?

  • Trường hợp 1: Khi chúng ta gọi hàm setState để cập nhật local state trong component.
  • Trường hợp 2: Khi mà component đó là con của component khác và props được truyền bị thay đổi.

Trong React còn có một em bí ẩn nữa là: shouldComponentUpdate. Nhiệm vụ chính của em nó là quyết xem có nên chạy hàm render của component đó không? Khi có một thay đổi từ state hoặc props, trước khi chạy hàm render, component sẽ trigger phương thức shouldComponentUpdate. Nếu giá trị hàm này trả về true thì render được chạy và ngược lại false, render sẽ không được chạy.

Một khi props được truyền từ cha của nó thay đổi, phương phức getDerivedStateFromProps(newProps, currentState) sẽ được khởi chạy. Hàm có hai tham số là props mới được thay đổi và những state hiện tại của component(local state). Một component có thể có local stateprops.

Mặc định nếu props thay đổi thì hàm render trong component được render lại? Vậy tại sao có một số lý do nào đó, khi props thay đổi nhưng component nhận props đó không nhận biết được. Đó là trường hợp, chúng ta init state từ một props nào đó. Ví dụ ta có một component như sau:

class EmailInput extends Component {
  state = { email: this.props.email };

  handleChange = event => {
    this.setState({ email: event.target.value });
  };
  render() {
    return <input onChange={this.handleChange} value={this.state.email} />;
  }
}

Chúng ta có một state là email được gán bằng this.props.email. Cách này đã làm cho component không còn nhận biết được khi nào props thay đổi nữa. Và một khi this.props.email thay đổi, chúng ta cài đặt phương pháp getDerivedStateFromProps để bắt được sự thay đổi của this.props. Sau đó, bạn có thể so sánh để quyết định trả về state mới như thế nào.

class EmailInput extends Component {
  state = {
    email: this.props.email
  };

  getDerivedStateFromProps(nextProps, currentState) {
    // Any time props.email changes, update state.
    if (nextProps.email !== currentState.email) {
      this.setState({
        email: nextProps.email
      });
    }
  }

  // ...
}

Một component như thế này được gọi là uncontrolled(stateful) component. Bởi vì nó tự có local state chứ không phải là một controlled(stateless) component.

Đó là một trường hợp bạn đã làm phức tạp cây component của bạn, việc xử lí getDerivedStateFromProps khá phức tạp và làm cho state trong component khó theo dõi sự thay đổi. React khuyên chúng ta không nên có quá nhiều uncontrolled component như thế này. Thay vào đó, chúng ta hãy biến nó thành stateless(thường gọi nó là dump component) chỉ có nhiệm vụ nhận props và emit event lên trên cho các Container xử lí. Bạn có thể tìm hiểu một số phương pháp để tránh khỏi dùng getDerivedStateFromProps.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *