ReactJS: Sự khác nhau giữa setState và useState

Chuyện kể rằng setState là một bí kíp ra đời đã từ lâu, khi mà chúng ta còn bị lẫn lộn giữa Class Component và Functional Component. Chúng ta tạo nên trang web thường có 2 dạng: tĩnh và động. Tĩnh là những trang web cơ bản chỉ render HTML, CSS chứ không có tương tác của người dùng làm thay đổi nội dung của nó. Một số ví dụ trang web tĩnh như: landing pages, blog, …

Trang web động là những trang web nó bị thay đổi liên tục về nội dung như cập nhật dữ liệu như các trang bán hàng, sàn gia dịch bitcoin, chứng khoán, web app, đặt vé, …

setState, useState đươc sử dụng nhiều để quản lí dữ liệu thay đổi trên web động. Những dữ liêu(state) thường cần được quản lí một cách chặt chẽ và khoa học để theo dõi, bảo trì và truy vết lỗi dễ dàng hơn. Trong web mọi sự phức tạp và khó khăn bắt đầu khi dữ liệu thay đổi. Và setState, useState sinh ra để giải quyết bài toán đó. Một bài toán khó nhằng, từng làm điên đầu các lập trình viên, đã làm cho nhiều chiến sĩ ngã ngựa như: Angular 1, Knockout, Backbone, Emberjs, ….

Một số lưu ý về setState

  • API: setState(updater, [callback]). Trong đó, updater có thể là một object hay một function. Callback sẽ được gọi ngay sau khi state đã được cập nhật với giá trị mới
this.setState((state, props) => {
  return {counter: state.counter + props.step};
});
// or
this.setState({quantity: 2})
  • State được khai báo và quản lí giống như những biến trong một hàm. Props thì giống như tham số được truyền vào cho một hàm. State bị thay đổi, props không thể thay đổi trực tiếp trong component mà nó được truyền vào.
  • setState được xử lý bất đồng bộ, có nghĩa là bạn sẽ phải chờ một lúc, để sau khi gọi setState thì giá trị mới được cập nhật. Bạn hãy tưởng tượng setState như là một API request là bất đồng bộ và chờ đợi để giá trị được cập nhật.
incrementCount() {
  this.setState({count: this.state.count + 1});
}

handleSomething() {
  // Giả sử `this.state.count` bắt đầu là 0.
  this.incrementCount();
  this.incrementCount();// giá trị this.state.count vẫn là 0
  this.incrementCount();// giá trị this.state.count vẫn là 0
}

Mỗi lần bạn gọi this.incrementCount() thì giá trị this.state.count vẫn là 0

Ví dụ được fix như sau:

incrementCount() {
  this.setState((state) => {
    // Important: read `state` instead of `this.state` when updating.
    return {count: state.count + 1}
  });
}

handleSomething() {
  // Let's say `this.state.count` starts at 0.
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();

  // If you read `this.state.count` now, it would still be 0.
  // But when React re-renders the component, it will be 3.
}
  • setState là bất đồng bộ để cải thiện performance cho app, tránh tình trạng render nhiều lần khi cả Child và Parent component đồng thời gọi setState
  • setState sẽ merge gía trị mới về Object state của this.state
constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }
componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts // update từng state riêng lẻ
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments // update từng state riêng lẻ
      });
    });
  }

Một số lưu ý về useState Hook

  • Chỉ được sử dụng trong functional component
  • useState cũng update state một cách bất đồng bộ như setState
  • Khác với setState, useState sẽ ghi đè lên state cũ, chứ không merge giá trị mới vào state ban đầu
  • Chỉ dùng useState cho React functional component, không dùng trong hàm thông thường
  • Nên sử dụng ESLint plugin để check một số lỗi như:
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
"react-hooks/exhaustive-deps": "warn" // Checks effect dependencies

Leave a Reply

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