Hãy tưởng tượng việc tăng một bộ đếm trong một số thành phần:
class SomeComponent extends Component{
state = {
updatedByDiv: '',
updatedByBtn: '',
counter: 0
}
divCountHandler = () => {
this.setState({
updatedByDiv: 'Div',
counter: this.state.counter + 1
});
console.log('divCountHandler executed');
}
btnCountHandler = () => {
this.setState({
updatedByBtn: 'Button',
counter: this.state.counter + 1
});
console.log('btnCountHandler executed');
}
...
...
render(){
return (
...
// a parent div
<div onClick={this.divCountHandler}>
// a child button
<button onClick={this.btnCountHandler}>Increment Count</button>
</div>
...
)
}
}
Có một trình xử lý đếm được gắn vào cả hai thành phần cha và con. Điều này được thực hiện có chủ đích để chúng tôi có thể thực thi setState () hai lần trong cùng bối cảnh bong bóng sự kiện nhấp chuột, nhưng từ trong 2 trình xử lý khác nhau.
Như chúng ta tưởng tượng, một sự kiện nhấp chuột vào nút bây giờ sẽ kích hoạt cả hai trình xử lý này vì bong bóng sự kiện từ mục tiêu đến thùng chứa ngoài cùng trong giai đoạn sủi bọt.
Do đó, btnCountHandler () thực thi trước, dự kiến sẽ tăng số đếm lên 1 và sau đó divCountHandler () thực thi, dự kiến sẽ tăng số đếm lên 2.
Tuy nhiên, số lượng chỉ tăng lên 1 khi bạn có thể kiểm tra trong các công cụ React Developer.
Điều này chứng tỏ rằng phản ứng
xếp hàng tất cả các cuộc gọi setState
quay lại hàng đợi này sau khi thực hiện phương thức cuối cùng trong ngữ cảnh (divCountHandler trong trường hợp này)
hợp nhất tất cả các đột biến đối tượng xảy ra trong nhiều lệnh gọi setState trong cùng một ngữ cảnh (tất cả các lệnh gọi phương thức trong một pha sự kiện là cùng một bối cảnh, ví dụ) thành một cú pháp đột biến đối tượng duy nhất (hợp nhất là lý do tại sao chúng ta có thể cập nhật các thuộc tính trạng thái một cách độc lập trong setState () ở vị trí đầu tiên)
và chuyển nó vào một setState () duy nhất để ngăn kết xuất lại do nhiều lệnh gọi setState () (đây là một mô tả rất nguyên thủy về việc tạo khối).
Mã kết quả chạy bằng phản ứng:
this.setState({
updatedByDiv: 'Div',
updatedByBtn: 'Button',
counter: this.state.counter + 1
})
Để dừng hành vi này, thay vì truyền các đối tượng làm đối số cho phương thức setState, các cuộc gọi lại được thông qua.
divCountHandler = () => {
this.setState((prevState, props) => {
return {
updatedByDiv: 'Div',
counter: prevState.counter + 1
};
});
console.log('divCountHandler executed');
}
btnCountHandler = () => {
this.setState((prevState, props) => {
return {
updatedByBtn: 'Button',
counter: prevState.counter + 1
};
});
console.log('btnCountHandler executed');
}
Sau khi phương thức cuối cùng kết thúc thực hiện và khi phản ứng trả về để xử lý hàng đợi setState, nó chỉ cần gọi lại cho mỗi setState được xếp hàng, chuyển qua trạng thái thành phần trước đó.
Cách phản ứng này đảm bảo rằng cuộc gọi lại cuối cùng trong hàng đợi được cập nhật trạng thái mà tất cả các đối tác trước đó đã đặt tay vào.