Уявіть собі збільшення лічильника в якомусь компоненті:
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>
...
)
}
}
Існує обробник лічильників, приєднаний як до батьківського, так і дочірнього компонентів. Це зроблено цілеспрямовано, щоб ми могли виконати setState () двічі в межах одного і того ж контексту, що перетворюється на події клацання, але зсередини двох різних обробників.
Як ми могли б уявити, подія одного клацання на кнопці тепер запустить обидва ці обробники, оскільки подія переходить від цільового до самого зовнішнього контейнера під час фази бульбашки.
Таким чином, btnCountHandler () виконує спочатку, очікується, що він зросте до 1, а потім виконує divCountHandler (), очікується, що кількість зросте до 2.
Однак нараховують лише кроки до 1, як це можна перевірити в інструментах React Developer.
Це доводить, що реагують
черга всіх викликів setState
повертається до цієї черги після виконання останнього методу в контексті (divCountHandler в цьому випадку)
об'єднує всі мутації об'єкта, що відбуваються в межах декількох викликів setState в одному контексті (усі виклики методу в рамках однієї фази події є одним і тим же контекстом, наприклад,) в один синтаксис мутації об'єкта (об'єднання має сенс, тому що ми можемо самостійно оновлювати властивості стану в setState () в першу чергу)
і передає його в один єдиний setState () для запобігання повторної рендерингу через кілька викликів setState () (це дуже примітивний опис пакетної обробки).
Код результату, керований реакцією:
this.setState({
updatedByDiv: 'Div',
updatedByBtn: 'Button',
counter: this.state.counter + 1
})
Для припинення такої поведінки замість передачі об'єктів як аргументів методу setState передаються зворотні виклики.
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');
}
Після того, як останній метод закінчує виконання, і коли react повертається для обробки черги setState, він просто викликає зворотний виклик для кожної черги setState, переходячи в попередній стан компонента.
Цей спосіб реагування гарантує, що останній зворотний виклик у черзі отримує оновлення стану, на який поклали всі попередні аналоги.