Immagina di incrementare un contatore in alcuni componenti:
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>
...
)
}
}
Esiste un gestore di conteggio collegato ai componenti padre e figlio. Questo viene fatto di proposito in modo da poter eseguire setState () due volte all'interno dello stesso contesto di bubbling dell'evento click, ma da 2 gestori diversi.
Come immaginiamo, un singolo clic sul pulsante ora attiverebbe entrambi questi gestori poiché l'evento bolle dal target al contenitore più esterno durante la fase di bubbling.
Pertanto btnCountHandler () viene eseguito per primo, si prevede che il conteggio aumenti a 1 e quindi divCountHandler () viene eseguito, si prevede che il conteggio aumenti a 2.
Tuttavia, il conteggio aumenta solo a 1, come è possibile esaminare negli strumenti di React Developer.
Questo dimostra che reagire
mette in coda tutte le chiamate setState
ritorna su questa coda dopo aver eseguito l'ultimo metodo nel contesto (divCountHandler in questo caso)
unisce tutte le mutazioni di oggetto che avvengono all'interno di più chiamate setState nello stesso contesto (tutte le chiamate di metodo all'interno di una singola fase di evento sono lo stesso contesto per esempio) in una sintassi di mutazione di singolo oggetto (l'unione ha senso perché è per questo che possiamo aggiornare le proprietà dello stato in modo indipendente in setState () in primo luogo)
e lo passa in un unico setState () per impedire il rendering di nuovo a causa di più chiamate setState () (questa è una descrizione molto primitiva del batch).
Il codice risultante eseguito da reazioni:
this.setState({
updatedByDiv: 'Div',
updatedByBtn: 'Button',
counter: this.state.counter + 1
})
Per interrompere questo comportamento, invece di passare oggetti come argomenti al metodo setState, i callback vengono passati.
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');
}
Al termine dell'esecuzione dell'ultimo metodo e quando reazioni ritorna per elaborare la coda setState, chiama semplicemente il callback per ogni setState in coda, passando nello stato componente precedente.
In questo modo reagire assicura che l'ultimo callback nella coda riesca ad aggiornare lo stato su cui tutte le sue controparti precedenti hanno messo le mani.