Wyobraź sobie, że zwiększasz licznik w jakimś komponencie:
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>
...
)
}
}
Istnieje procedura obsługi zliczania dołączona zarówno do składnika nadrzędnego, jak i podrzędnego. Odbywa się to celowo, abyśmy mogli dwukrotnie wykonać setState () w tym samym kontekście propagacji zdarzenia kliknięcia, ale z poziomu 2 różnych programów obsługi.
Jak możemy sobie wyobrazić, pojedyncze zdarzenie kliknięcia przycisku wyzwoli teraz oba te programy obsługi, ponieważ zdarzenie przechodzi z celu do najbardziej zewnętrznego kontenera podczas fazy propagacji.
Dlatego btnCountHandler () jest wykonywana jako pierwsza, oczekuje się, że zwiększy licznik do 1, a następnie wykonuje divCountHandler (), oczekując, że zwiększy licznik do 2.
Jednak liczba wzrasta tylko do 1, co można sprawdzić w narzędziach React Developer.
To dowodzi, że reagujemy
kolejkuje wszystkie wywołania setState
wraca do tej kolejki po wykonaniu ostatniej metody w kontekście (w tym przypadku divCountHandler)
łączy wszystkie mutacje obiektów zachodzące w wielu wywołaniach setState w tym samym kontekście (wszystkie wywołania metod w jednej fazie zdarzenia mają ten sam kontekst np.) w jedną składnię mutacji obiektu (scalanie ma sens, ponieważ dlatego możemy niezależnie aktualizować właściwości stanu w setState () na pierwszym miejscu)
i przekazuje go do jednej pojedynczej metody setState (), aby zapobiec ponownemu renderowaniu z powodu wielu wywołań setState () (jest to bardzo prymitywny opis przetwarzania wsadowego).
Wynikowy kod uruchomiony przez React:
this.setState({
updatedByDiv: 'Div',
updatedByBtn: 'Button',
counter: this.state.counter + 1
})
Aby zatrzymać to zachowanie, zamiast przekazywania obiektów jako argumentów do metody setState, przekazywane są wywołania zwrotne.
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');
}
Gdy ostatnia metoda zakończy wykonywanie i gdy reakcja powróci do przetworzenia kolejki setState, po prostu wywołuje wywołanie zwrotne dla każdego ustawionego w kolejce setState, przekazując poprzedni stan komponentu.
W ten sposób reakcja zapewnia, że ostatnie wywołanie zwrotne w kolejce zaktualizuje stan, w którym wszystkie poprzednie odpowiedniki położyły w ręce.