Stateless vs Stateful Components

So sánh Stateless và Stateful Components

Ngoài 2 tên gọi này, 2 dạng component này còn có một số cách gọi khác. Chẳng hạn như:

  • Container vs Presentational components

  • Smart vs Dumb components

Stateful/Container/Smart component là thế nào?

class StatefullComponent extends Component {
 constructor() {
   super()
   this.state = {
     books: [],
     count: 0
   }
 }
 
 handleCount(value) {
    this.setState({count:this.state.count + value});
}

 render() {
   <BooksList books={this.state.books} handleCount={this.handleCount} />
 }
}

Stateful component luôn là class component. Các stateful components có một state được khởi tạo trong constructor.

Các React component cung cấp một phương thức gọi là setState dùng để cập nhật state. setState chấp nhận một object chứa trạng thái mới của count.

setState() chấp nhận một object như một tham số đầu vào, và chúng ta tăng giá trị trước của count lên 1 số value, nó sẽ làm việc như mong đợi. Tuy nhiên, có một nhược điểm. Khi có nhiều lời gọi setState mà đọc giá trị trước đó của state và viết một giá trị mới vào nó, chúng ta có thể kết thúc với race condition (là một tình huống xảy ra khi nhiều threads cùng truy cập và cùng lúc muốn thay đổi dữ liệu). Vì setState chạy bất đồng bộ. Điều này có nghĩa là kết quả cuối cùng sẽ không khớp với các giá trị mong muốn. Do đó, thay vì trực tiếp truyền vào một object, bạn có thể truyền vào đó một hàm updater có cú pháp: (prevState, props) => stateChange prevState là một tham chiếu đến state trước và được bảo đảm là mới nhất. Props đề cập đến các props của component, và chúng ta không cần props để cập nhật state ở đây, vì vậy chúng ta có thể bỏ qua tham số đó. Do đó, chúng ta có thể sử dụng cách này để cập nhật state và tránh được race condition.

// Cách dùng đúng
handleCount(value) {     
  this.setState((prevState) => {
    count: prevState.count + value
  });
}

setState() render lại component, và bạn có một stateful component hoạt động tốt.

Vậy còn Stateless/Presentational/Dumb component ?

const StatelessComponent = ({books}) => {
 return (
   <ul>
     {books.map(book => {
       return <li>book</li>
     })}
   </ul>
 )
}

Bạn có thể sử dụng một function hoặc một Class để tạo ra các stateless components. Nhưng trừ khi bạn cần sử dụng vòng đời trong các component của mình, không thì bạn nên sử dụng stateless functional component. Có rất nhiều lợi ích nếu bạn quyết định sử dụng stateless functional component ở đây:

  • Chúng rất dễ viết,dễ hiểu và dễ kiểm tra

  • Bạn có thể tránh được từ khoá this hoàn toàn.

Tuy nhiên, theo React v16, không có lợi ích về hiệu suất từ việc sử dụng các stateless functional component thay cho class component. Nhược điểm là bạn không thể sử dụng vòng đời của React Component. Một phương thức của vòng đời là shouldComponentUpdate() thường được sử dụng để tối ưu hóa hiệu suất và tự kiểm soát những gì được render lại. Bạn không thể sử dụng nó với các functional components. Và refs cũng không được hỗ trợ.

Vậy thì khi nào ta nên chọn Statefull component và khi nào nên chọn Stateless?

Chúng ta có thể nhìn vào ưu nhược điểm của 2 loại này rồi từ đó đưa ra lựa chọn thích hợp:

Ưu điểm của stateless:

  • Stateless là cách đơn giản nhất để định nghĩa 1 component trong React. Nếu ta không cần quản lý bất kỳ state nào, thì đây là cách làm hợp lý bởi điểm khác biệt lớn nhất của việc sử dụng function thay vì class là bạn có thể hoàn toàn đảm bảo rằng output của nó chỉ phụ thuộc vào input được cấp cho hàm(props).

  • App của bạn nên hướng tới mục tiêu có nhiều component stateless nhất có thể, bởi điều đó khiến bạn có thể quản lý logic của app dễ dàng hơn, cũng như dễ dàng test và tái sử dụng...

Tuy nhiên ưu điểm của Stateless component lại là nhược điểm trong một số trường hợp:

  • Nó không có các phương thức trong lifecycle, bởi vậy bạn sẽ không thể tạo các các xử lý logic đặc thù như với Component hay Pure component

  • Không có cách nào để kiểm soát việc render. Việc re-render xảy ra liên tục mỗi khi component cha của nó có cập nhật.

  • Không hỗ trợ Refs

Như vậy, tuy Functional stateless Components đem lại lợi ích giúp việc quản lý logic trở nên đơn giản hơn nhưng nó lại có nhược điểm về mặt performance, bởi việc tối ưu render đã không còn được như ở React.Component hay Pure Component.

Last updated