Así que he estado haciendo React-Native durante un par de meses y me encontré con una situación en la que una gran parte tenía que actualizarse en la función setState. Tuve que llamar a una función después que dependía de ese estado. Por supuesto, el estado no mutó de inmediato desde que supe que setState es asíncrono.
Esta es mi estructura
Padre
stateSetter = (data) => { this.setState({ ...data }) } dateFilter = () => { let startDate = this.state.startDate let endDate = this.state.endDate if (startDate !== "" && endDate == "") { this.setState({ DataFiltered: this.state.Data.filter(elem => Helper.convertDateToISO(elem.date)>= Helper.convertDateToISO(startDate)) }) }else if(startDate == "" && endDate !== ""){ this.setState({ DataFiltered: this.state.Data.filter(elem => Helper.convertDateToISO(elem.date)<= Helper.convertDateToISO(endDate)) }) }else if(startDate !== "" && endDate !== ""){ this.setState({ DataFiltered: this.state.Data.filter(elem => Helper.convertDateToISO(elem.date)>= Helper.convertDateToISO(startDate) && Helper.convertDateToISO(elem.date)<= Helper.convertDateToISO(endDate)) }) }else if(startDate === "" && endDate === ""){ this.setState({ DataFiltered: this.state.Data }) } }Niño
<TouchableWithoutFeedback onPress={async () => { await stateSetter({ ["startDate"]: "", ["endDate"]: "", ["startDateText"]: "From...", ["endDateText"]: "To..." }) dateFilter() }} >Ahora tenía la creencia de que Async Await funciona solo cuando await está esperando una promesa... ¿verdad? Entonces, según esa lógica, en el código mencionado anteriormente, await y async no deberían tener ningún efecto en el programa.
au contraire
Cuando no uso async await, no funciona. Solo funciona cuando uso async await.
Cuando estaba aprendiendo sobre async, probé un par de cosas y ninguna funcionó.
this.setState({ ...data }, () => { this.dateFilter() }) //Had no effectAdemás: Promesa no tuvo efecto.
TlDr: ¿Por qué funciona mi Async Await?
tl; dr: debido a que está utilizando await , el resto de la función está programada para ejecutarse en el futuro y en ese momento el estado se habrá actualizado. Si realmente estás await una promesa o no, es irrelevante.
No conozco el funcionamiento interno de React, pero asumo que la cola es una microtarea para actualizar el estado. Las devoluciones de llamada de promesa también se procesan como una microtarea (y async/await es solo una buena manera de trabajar con promesas).
Entonces, primero React agrega una microtarea para actualizar el estado, y luego await agrega una microtarea para reanudar la función.
De hecho, podemos hacer un experimento simple para verificar cuál es el orden de los eventos al pasar una devolución de llamada a setState (no JSX porque de alguna manera no pude convertirlo en un fragmento de código funcional):
class Component extends React.Component { async doStuff() { await this.setState({newState: true}, () => console.log('inside setState callback', JSON.stringify(this.state))); console.log('after await this.setState', JSON.stringify(this.state)); } render() { return React.createElement('button', {onClick: () => this.doStuff()}, 'Click me'); } } ReactDOM.render( React.createElement(Component), document.body ); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>Si ejecuta esto, verá que la devolución de llamada se llama primero. Sabemos que el estado se ha actualizado en este punto porque ese es el propósito de la devolución de llamada: se ejecuta cuando se ha actualizado el estado.
Luego se ejecuta el resto de la función, y dado que el estado ya se actualizó, accederá al nuevo estado.
Sin embargo, dado que se está preguntando por qué funciona esto, recomendaría esta práctica y solo usaría la devolución de llamada setState .
Para hacer que await sea aplicable para stateSetter, debe devolver una Promesa
stateSetter = (data) => { return new Promise(resolve => setTimeout(resolve, 3000)); }