Trong thế giới của React, việc hiểu rõ bản chất của Stateful và Stateless components cũng quan trọng như việc một đầu bếp hiểu khi nào cần dùng lửa to và khi nào cần liu riu. Đây không chỉ là những khái niệm lý thuyết suông, mà là nền tảng cốt lõi quyết định cách bạn cấu trúc ứng dụng, tối ưu hóa hiệu năng và viết code sạch sẽ, dễ bảo trì.
Hãy cùng nhau bóc tách từng lớp, từ định nghĩa kinh điển đến cuộc cách mạng mang tên "Hooks" đã thay đổi cuộc chơi như thế nào!
🎨 Stateless Component: "Người trình bày" trung thành
Hãy tưởng tượng một người họa sĩ chỉ nhận nhiệm vụ vẽ lại một bức tranh theo mẫu có sẵn. Bạn đưa cho anh ta màu gì, cọ gì, anh ta sẽ vẽ ra chính xác bức tranh đó. Anh ta không tự ý thêm thắt hay thay đổi chi tiết. Đó chính là Stateless Component.
Stateless Components, hay còn được gọi là Presentational Components (thành phần trình bày) hoặc Dumb Components (thành phần "ngốc"), là những component đơn giản nhất trong React.
Đặc điểm nhận dạng:
- Không có
state
của riêng mình: Chúng không lưu trữ bất kỳ dữ liệu nào thay đổi theo thời gian. Cuộc đời của chúng là một đường thẳng, không có ký ức. - Nhận dữ liệu qua
props
: Giống như người họa sĩ nhận "mẫu" (dữ liệu) từ bên ngoài thông quaprops
và chỉ có một nhiệm vụ duy nhất - hiển thị dữ liệu đó ra giao diện. - Dự đoán được: Với cùng một
props
đầu vào, chúng sẽ luôn luôn trả về cùng một kết quả (UI) đầu ra. Điều này làm cho chúng rất dễ kiểm thử (test). - Thường là Function Components: Trước khi Hooks ra đời, đây là cách viết phổ biến nhất cho Stateless Components.
Ví dụ kinh điển: Một component Welcome
đơn giản.
// Welcome.js - Một Stateless Function Component điển hình
import React from 'react'
function Welcome(props) {
return <h1>Chào mừng, {props.name}!</h1>
}
export default Welcome
Trong ví dụ này, Welcome
không cần biết name
đến từ đâu hay nó sẽ thay đổi như thế nào. Nó chỉ nhận name
và hiển thị. Đơn giản, hiệu quả và có khả năng tái sử dụng cực cao.
🧠 Stateful Component: "Bộ não" thông minh
Ngược lại với người họa sĩ ở trên, hãy tưởng tượng một vị quản lý kho hàng. Vị quản lý này không chỉ biết cách trưng bày hàng hóa (render
), mà còn phải ghi nhớ trong kho còn bao nhiêu sản phẩm, khi nào cần nhập thêm, khi nào xuất hàng đi. Ông ta có "trí nhớ" và "logic" riêng. Đó chính là Stateful Component.
Stateful Components, hay còn gọi là Container Components (thành phần bao bọc) hoặc Smart Components (thành phần "thông minh"), là bộ não của ứng dụng React.
Đặc điểm nhận dạng:
- Quản lý
state
: Chúng sở hữu một đối tượngstate
để lưu trữ dữ liệu có thể thay đổi theo tương tác của người dùng hoặc các sự kiện khác. Đây là "trí nhớ" của component. - Chứa logic nghiệp vụ: Chúng chịu trách nhiệm xử lý các sự kiện, gọi API, và quyết định xem nên hiển thị cái gì và khi nào.
- Sử dụng
setState()
để cập nhật UI: Khistate
thay đổi, chúng sử dụng phương thứcsetState()
để "ra lệnh" cho React render lại giao diện với dữ liệu mới. - Thường là Class Components: Đây là cách duy nhất để tạo ra Stateful Components trước khi có Hooks. Chúng sử dụng các phương thức vòng đời (lifecycle methods) như
componentDidMount
haycomponentDidUpdate
.
Ví dụ kinh điển: Một component Counter
(bộ đếm).
// Counter.js - Một Stateful Class Component điển hình
import React, { Component } from 'react'
class Counter extends Component {
constructor(props) {
super(props)
// Khởi tạo state ban đầu
this.state = {
count: 0,
}
}
// Phương thức để thay đổi state
increment = () => {
this.setState({ count: this.state.count + 1 })
}
render() {
return (
<div>
<p>Số lượt bấm: {this.state.count}</p>
<button onClick={this.increment}>Bấm vào tôi</button>
</div>
)
}
}
export default Counter
Component này có state
là count
. Mỗi khi người dùng bấm nút, nó tự cập nhật state
của mình và hiển thị lại giá trị mới.
⚖️ Đặt lên bàn cân: Stateful vs. Stateless
Dưới đây là bảng so sánh nhanh theo các tiêu chí quan trọng nhất:
Tiêu chí | Stateless Component (Dumb) | Stateful Component (Smart) |
---|---|---|
Mục đích | Hiển thị dữ liệu, giao diện (UI). | Quản lý dữ liệu, logic nghiệp vụ. |
State | Không có state . | Có state để lưu trữ dữ liệu. |
Cú pháp | Function Component. | Class Component. |
Dữ liệu | Nhận dữ liệu từ props . | Quản lý dữ liệu nội bộ bằng state . |
Vòng đời | Không có lifecycle methods. | Có các lifecycle methods (componentDidMount ...). |
Khi nào dùng | Các thành phần UI tái sử dụng: Button, Input, Card... | Các trang, các khu vực quản lý logic phức tạp. |
💥 Cuộc cách mạng mang tên "Hooks" - Khi ranh giới bị xóa nhòa
Mô hình Class Component (Stateful) và Function Component (Stateless) đã phục vụ cộng đồng React rất tốt trong một thời gian dài. Tuy nhiên, nó cũng bộc lộ một số nhược điểm: Class Components
khá dài dòng, logic khó tái sử dụng, và khái niệm this
đôi khi gây bối rối.
Và rồi, React Hooks ra đời trong phiên bản React 16.8, làm thay đổi mọi thứ.
Hooks là những hàm đặc biệt cho phép bạn "móc" các tính năng của React (như state và lifecycle) vào trong Function Components.
Điều này có nghĩa là: Function Components giờ đây cũng có thể trở thành "Stateful"!
Hãy xem lại ví dụ Counter
ở trên, nhưng lần này được viết lại bằng Function Component và Hook useState
:
// Counter.js - VIẾT LẠI theo phong cách Hooks hiện đại
import React, { useState } from 'react'
function Counter() {
// Dùng Hook `useState` để tạo ra một "state" trong Function Component
// `count` là giá trị state, `setCount` là hàm để cập nhật nó
const [count, setCount] = useState(0)
const increment = () => {
setCount(count + 1)
}
return (
<div>
<p>Số lượt bấm: {this.state.count}</p>
<button onClick={increment}>Bấm vào tôi</button>
</div>
)
}
export default Counter
Kết quả? Code ngắn gọn hơn, dễ đọc hơn, không còn this
, và vẫn hoàn toàn là một Stateful Component. Ranh giới giữa "thông minh" và "ngốc" dựa trên cú pháp (Class vs. Function) đã bị xóa nhòa.
💡 Bí kíp tối ưu: Khi nào dùng gì trong kỷ nguyên Hooks?
Với sự xuất hiện của Hooks, cộng đồng React hiện nay ưu tiên sử dụng Function Components cho gần như mọi trường hợp. Tuy nhiên, tư duy phân tách "logic" và "trình bày" vẫn còn nguyên giá trị.
✅ Quy tắc vàng:
- Luôn bắt đầu với Function Component. Đây là tiêu chuẩn hiện đại.
- Mặc định component là "stateless". Chỉ tập trung vào việc nhận
props
và hiển thị UI. - Khi cần "trí nhớ", hãy thêm Hooks. Nếu component cần lưu trữ dữ liệu (ví dụ: giá trị của một ô input, trạng thái đóng/mở của một menu), hãy sử dụng Hook
useState
. - Khi cần xử lý "side effects", hãy thêm Hooks. Nếu component cần tương tác với thế giới bên ngoài (gọi API, thao tác DOM), hãy sử dụng Hook
useEffect
. - Tách biệt logic phức tạp. Nếu một component trở nên quá "thông minh" với nhiều state và effect, hãy cân nhắc tách phần logic đó ra một Custom Hook để tái sử dụng.
Việc phân chia này không còn là Stateful vs. Stateless một cách cứng nhắc, mà là sự phân tách linh hoạt giữa Container Logic (quản lý state và side effects) và Presentational Logic (hiển thị UI) ngay trong cùng một Function Component hoặc giữa các Function Components khác nhau.
Kết luận: Cần hiểu rõ bản chất của state
Hành trình từ việc phân biệt rạch ròi giữa Stateful (Class) và Stateless (Function) đến kỷ nguyên Hooks cho thấy sự phát triển không ngừng của React.
- Stateless Component: Vẫn là những người hùng thầm lặng, chuyên tâm vào việc hiển thị, giúp ứng dụng của bạn dễ kiểm thử và tái sử dụng.
- Stateful Component: Là bộ não điều khiển, nơi chứa đựng logic và dữ liệu.
- React Hooks: Là cuộc cách mạng cho phép chúng ta xây dựng những "bộ não" mạnh mẽ bằng cú pháp Function Component đơn giản, gọn gàng và hiện đại hơn.
Hiểu rõ bản chất của state và cách quản lý nó chính là chìa khóa để bạn chinh phục React và xây dựng nên những ứng dụng tuyệt vời.
Chúc bạn thành công trên con đường coding của mình!