React controlled component và uncontrolled component
Bài đăng này đã không được cập nhật trong 3 năm
Trong hầu hết các trường hợp chúng ta thường cài đặt các component trong react dưới dạng controlled components
. Có thể hiểu controlled components
là các dữ liệu trong form đều được React quản lí thường dưới dạng state hoặc store. Còn uncontrolled components
thì khác, dữ liệu được lấy trực tiếp từ DOM. Để hiểu chi tiết ta sẽ đi sâu hơn vào 2 lại component này.
Controlled component
Đầu tiên tôi sẽ lấy một ví dụ về controlled component
. Có thể bạn thấy ví dụ này sẽ rất quent huộc bởi vì hầu hết đa số các trường hợp ta đều dùng controlled component
class Form extends Component {
constructor() {
super();
this.state = {
name: '',
};
}
handleNameChange = (event) => {
this.setState({ name: event.target.value });
};
render() {
return (
<div>
<input
type="text"
value={this.state.name}
onChange={this.handleNameChange}
/>
</div>
);
}
}
Trong ví dụ trên bạn có thể thấy dữ liệu của form được lữu trữ/quản lí bởi state của component. Mỗi khi bạn thay đổi input thì handleNameChange
được gọi và nó sẽ cập nhật giá trị mới cho state. Sau khi state thay đổi thì nó sẽ render lại form với giá trị tương ứng với giá trị của state.
. Giá trị khởi tạo của state.name sẽ là một string rỗng ''.
. Khi bạn gõ 'a' vào ô input thì handleNameChange
sẽ được gọi và cập nhật lại giá trị mới cho state là a
. Tiếp đó là ô input sẽ được render lại với giá trị là state.name
. Khi bạn gõ tiếp 'b' thì logic cũng tương tự. Khi đó state.name sẽ có giá trị là 'ab' và giá trị này sẽ là giá trị của input khi render lại.
Trong ví dụ trên ta có thể thấy là giá trị của ô input luôn luôn tương ứng với giá trị 'state.name' của component. Ta có thể hiểu là ô input trong ví dụ trên luôn luôn hiển thị giá trị của state.name
Uncontrolled component
Tiếp theo ta sẽ đến với uncontrolled component
. Để viết một uncontrolled component
khá đơn giản là bạn sẽ ko viết các event bắt sự kiện thay đổi input trong form mà bạn sẽ sử dụng một tham chiếu trực tiếp đến DOM. Dưới đây là một ví dụ đơn giản
class NameForm extends React.Component {
constructor(props) {
super(props);
}
handleSubmit = event => {
alert('A name was submitted: ' + this.input.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={(input) => this.input = input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Trong ví dụ trên, ta đặt một biến tham chiếu là input tham chiếu đến DOM object. Khi cần lấy giá trị ta sẽ truy xuất giá trị thông qua tham chiếu này.
Chú ý: Việc khởi tạo giá trị cho input trong trường hợp dùng uncontrolled component
khác với controlled component
. Bạn ko thể dùng thuộc tính value
mà dùng thuộc tính defaultValue
bởi vì nếu bạn dùng thuộc tính value
thì mỗi khi form render lại nó sẽ luôn set giá trị này cho input, còn defaultValue chỉ set duy nhất lần đầu tiên khi khởi tạo form.
Vậy uncontrolled component dùng trong hoàn cảnh nào?
Theo tôi uncontrolled component
nên dùng cho các hệ thống, chức năng đơn giản. Khi đó sẽ phát huy được ưu điểm của nó là cài đặt đơn giản và nhanh. Hơn nữa tương tác người dùng sẽ tốt hơn bởi vì trang web sẽ ko phải render lại mỗi lần thay đổi giá trị của input.
Đối với một chức năng phức tạp các dữ liệu có liên hệ mật thiết với nhau hoặc có nhiều logic liên quan đến dữ liệu thì bạn nên cài đặt với controlled components (quản lí dữ liệu với state hoặc store). Như thế sẽ làm cho dữ liệu của bạn trở nên rõ ràng và dễ quản lí hơn rất nhiều.
Ta có một bảng so sánh với uncontrolled component
và controlled component
feature | uncontrolled | controlled |
---|---|---|
Lấy dữ liệu từ input | ✅ | ✅ |
Validate dữ liệu khi submit | ✅ | ✅ |
Validate của input mỗi khi thay đổi input | ❌ | ✅ |
Validate cả form mỗi khi một input trong form thay đổi | ❌ | ✅ |
Đảm bảo input theo một format nào đấy | ❌ | ✅ |
Số lượng inputs trong form thay đổi tùy theo điều kiện | ❌ | ✅ |
Từ bảng trên bạn có thể thấy là với controlled component
bạn có thể làm rất nhiều việc. Tuy nhiên với sự đơn giản của uncontrolled component
nó vẫn được sử dụng tốt với những form đơn giản không có nhiều yêu cầu đặc biệt.
Tham khảo:
All rights reserved