javascript - tiempo - ¿Puedo ejecutar una función después de que setState haya terminado de actualizar?
esperar que termine una funcion javascript (4)
Soy muy nuevo en React JS (como en, recién comencé hoy). No entiendo cómo funciona setState. Estoy combinando React y Easel JS para dibujar una cuadrícula basada en la entrada del usuario. Aquí está mi bin JS: http://jsbin.com/zatula/edit?js,output
Aquí está el código:
var stage;
var Grid = React.createClass({
getInitialState: function() {
return {
rows: 10,
cols: 10
}
},
componentDidMount: function () {
this.drawGrid();
},
drawGrid: function() {
stage = new createjs.Stage("canvas");
var rectangles = [];
var rectangle;
//Rows
for (var x = 0; x < this.state.rows; x++)
{
// Columns
for (var y = 0; y < this.state.cols; y++)
{
var color = "Green";
rectangle = new createjs.Shape();
rectangle.graphics.beginFill(color);
rectangle.graphics.drawRect(0, 0, 32, 44);
rectangle.x = x * 33;
rectangle.y = y * 45;
stage.addChild(rectangle);
var id = rectangle.x + "_" + rectangle.y;
rectangles[id] = rectangle;
}
}
stage.update();
},
updateNumRows: function(event) {
this.setState({ rows: event.target.value });
this.drawGrid();
},
updateNumCols: function(event) {
this.setState({ cols: event.target.value });
this.drawGrid();
},
render: function() {
return (
<div>
<div className="canvas-wrapper">
<canvas id="canvas" width="400" height="500"></canvas>
<p>Rows: { this.state.rows }</p>
<p>Columns: {this.state.cols }</p>
</div>
<div className="array-form">
<form>
<label>Number of Rows</label>
<select id="numRows" value={this.state.rows} onChange={ this.updateNumRows }>
<option value="1">1</option>
<option value="2">2</option>
<option value ="5">5</option>
<option value="10">10</option>
<option value="12">12</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
<label>Number of Columns</label>
<select id="numCols" value={this.state.cols} onChange={ this.updateNumCols }>
<option value="1">1</option>
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="12">12</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
</form>
</div>
</div>
);
}
});
ReactDOM.render(
<Grid />,
document.getElementById("container")
);
Puede ver en el contenedor JS cuando cambia el número de filas o columnas con uno de los menús desplegables, no pasará nada la primera vez. La próxima vez que cambie un valor desplegable, la cuadrícula dibujará los valores de fila y columna del estado anterior. Supongo que esto está sucediendo porque mi función this.drawGrid () se está ejecutando antes de que se complete setState. Tal vez hay otra razón?
¡Gracias por tu tiempo y ayuda!
Hacer que
setState
devuelva una
Promise
Además de pasar una
callback
de
callback
al método
setState()
, puede
setState()
alrededor de una función
async
y usar el método
then()
, que en algunos casos puede producir un código más limpio:
(async () => new Promise(resolve => this.setState({dummy: true}), resolve)()
.then(() => { console.log(''state:'', this.state) });
Y aquí puede dar un paso más y hacer una función
setState
reutilizable que, en mi opinión, es mejor que la versión anterior:
const promiseState = async state =>
new Promise(resolve => this.setState(state, resolve));
promiseState({...})
.then(() => promiseState({...})
.then(() => {
... // other code
return promiseState({...});
})
.then(() => {...});
Esto funciona bien en React 16.4, pero aún no lo he probado en versiones anteriores de React .
También vale la pena mencionar que mantener el código de
devolución de llamada
en el método
componentDidUpdate
es una mejor práctica en la mayoría, probablemente en todos los casos.
cuando se reciben nuevos accesorios o estados (como llama a
setState
aquí), React invocará algunas funciones, que se llaman
componentWillUpdate
y
componentDidUpdate
en su caso, simplemente agregue una función
componentDidUpdate
para llamar a
this.drawGrid()
aquí está el código de trabajo en JS Bin
Como mencioné, en el código, se invocará
componentDidUpdate
después de
this.setState(...)
entonces
componentDidUpdate
dentro va a llamar a
this.drawGrid()
Lea más sobre el ciclo de vida del componente en React https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate
render
llamará a
render
cada vez que
setState
para volver a renderizar el componente si hay cambios.
Si mueve su llamada a
drawGrid
allí en lugar de llamarla en sus métodos de
update*
, no debería tener ningún problema.
Si eso no funciona para usted, también hay una sobrecarga de
setState
que toma una devolución de llamada como segundo parámetro.
Debería poder aprovechar eso como último recurso.
setState(updater[, callback])
es una función asíncrona:
https://facebook.github.io/react/docs/react-component.html#setstate
Puede ejecutar una función después de que setState termine utilizando la segunda
callback
parámetro como:
this.setState({
someState: obj
}, () => {
this.afterSetStateFinished();
});