javascript - renderizar - this.setstate not working
¿Por qué llamar al método react setState no muta el estado inmediatamente? (6)
En pocas palabras, this.setState ({data: value}) es de naturaleza asíncrona, lo que significa que se sale de la Pila de llamadas y solo vuelve a la Pila de llamadas a menos que se resuelva.
Lea acerca de Event Loop para tener una idea clara de la naturaleza asincrónica en JS y por qué toma tiempo actualizarse.
https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4
Por lo tanto
this.setState({data:value});
console.log(this.state.data); // will give undefined or unupdated value
ya que lleva tiempo actualizar. Para lograr el proceso anterior:
this.setState({data:value},function () {
console.log(this.state.data);
});
Estoy leyendo la sección Forms de la documentación de reactjs y acabo de probar este código para demostrar el uso de JSBIN ( JSBIN ).
var React= require(''react'');
var ControlledForm= React.createClass({
getInitialState: function() {
return {
value: "initial value"
};
},
handleChange: function(event) {
console.log(this.state.value);
this.setState({value: event.target.value});
console.log(this.state.value);
},
render: function() {
return (
<input type="text" value={this.state.value} onChange={this.handleChange}/>
);
}
});
React.render(
<ControlledForm/>,
document.getElementById(''mount'')
);
Cuando actualizo el valor
<input/>
en el navegador, el segundo
console.log
dentro de la
handleChange
llamada
handleChange
imprime el mismo
value
que el primer
console.log
, ¿Por qué no puedo ver el resultado de
this.setState({value: event.target.value})
en el ámbito de la devolución de llamada
handleChange
?
Como se menciona en la documentación de React, no hay garantía de que
setState
se
setState
sincrónicamente, por lo que su
console.log
puede devolver el estado antes de su actualización.
Michael Parker menciona pasar una devolución de llamada dentro de
setState
.
Otra forma de manejar la lógica después del cambio de estado es a través del método del ciclo de vida de
componentDidUpdate
, que es el método recomendado en los documentos de React.
En general, recomendamos usar componentDidUpdate () para dicha lógica.
Esto es particularmente útil cuando puede haber sucesivos
setState
disparados, y le gustaría
setState
la misma función después de cada cambio de estado.
En lugar de agregar una devolución de llamada a cada
setState
, puede colocar la función dentro del
componentDidUpdate
, con lógica específica dentro si es necesario.
// example
componentDidUpdate(prevProps, prevState) {
if (this.state.value > prevState.value) {
this.foo();
}
}
Cuidado con los métodos de reacción del ciclo de vida!
- http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
- https://reactjs.org/docs/react-component.html
Trabajé durante varias horas para descubrir que se
getDerivedStateFromProps
a
getDerivedStateFromProps
después de cada
setState()
.
😂
De la documentation de React:
setState()
no muta inmediatamentethis.state
pero crea una transición de estado pendiente. Acceder athis.state
después de llamar a este método puede devolver el valor existente. No hay garantía de operación síncrona de llamadas asetState
y las llamadas pueden ser agrupadas para obtener ganancias de rendimiento.
Si desea que se ejecute una función después de que ocurra el cambio de estado, páselo como devolución de llamada.
this.setState({value: event.target.value}, function () {
console.log(this.state.value);
});
Puede intentar usar ES7 async / await. Por ejemplo, usando su ejemplo:
handleChange: async function(event) {
console.log(this.state.value);
await this.setState({value: event.target.value});
console.log(this.state.value);
}
async-await
sintaxis
async-await
funciona perfectamente para algo como lo siguiente ...
changeStateFunction = () => {
// Some Worker..
this.setState((prevState) => ({
year: funcHandleYear(),
month: funcHandleMonth()
}));
goNextMonth = async () => {
await this.changeStateFunction();
const history = createBrowserHistory();
history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}
goPrevMonth = async () => {
await this.changeStateFunction();
const history = createBrowserHistory();
history.push(`/calendar?year=${this.state.year}&month=${this.state.month}`);
}