Je suis très nouveau en React JS (comme dans, vient de commencer aujourd'hui). Je ne comprends pas très bien comment setState fonctionne. Je combine React et Easel JS pour dessiner une grille basée sur les entrées de l'utilisateur. Voici mon bin JS: http://jsbin.com/zatula/edit?js,output
Voici le code:
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")
);
Vous pouvez voir dans la corbeille JS que lorsque vous modifiez le nombre de lignes ou de colonnes à l'aide de l'une des listes déroulantes, rien ne se produit la première fois. La prochaine fois que vous modifierez une valeur de liste déroulante, la grille affichera les valeurs de ligne et de colonne de l'état précédent. Je suppose que cela se produit car ma fonction this.drawGrid () s’exécute avant la fin de setState. Peut-être il y a une autre raison?
Merci pour votre temps et votre aide!
setState(updater[, callback])
est une fonction asynchrone:
https://facebook.github.io/react/docs/react-component.html#setstate
Vous pouvez exécuter une fonction après la fin de setState en utilisant le deuxième paramètre callback
comme:
this.setState({
someState: obj
}, () => {
this.afterSetStateFinished();
});
render
sera appelé à chaque fois que vous setState
restituera le composant s'il y a des modifications. Si vous déplacez votre appel vers drawGrid
plutôt que de l'appeler dans vos méthodes update*
, vous ne devriez pas avoir de problème.
Si cela ne fonctionne pas pour vous, il existe également une surcharge de setState
qui prend un rappel en tant que second paramètre. Vous devriez pouvoir en profiter en dernier recours.
setState
retourne un Promise
En plus de passer d'une méthode callback
à setState()
, vous pouvez l'enrouler autour d'une fonction async
et utiliser la méthode then()
, qui peut parfois produire un code plus propre. :
(async () => new Promise(resolve => this.setState({dummy: true}), resolve)()
.then(() => { console.log('state:', this.state) });
Et ici, vous pouvez faire un pas de plus et créer une fonction réutilisable setState
qui, à mon avis, est meilleure que la version ci-dessus:
const promiseState = async state =>
new Promise(resolve => this.setState(state, resolve));
promiseState({...})
.then(() => promiseState({...})
.then(() => {
... // other code
return promiseState({...});
})
.then(() => {...});
Cela fonctionne très bien dans React 16.4, mais je ne l’ai pas encore testé dans les versions précédentes de React.
Il convient également de mentionner que le maintien de votre méthode rappel dans componentDidUpdate
est une meilleure pratique dans la plupart des cas, probablement dans tous les cas.
quand de nouveaux accessoires ou états sont reçus (comme vous appelez setState
ici), React invoquera certaines fonctions, appelées componentWillUpdate
et componentDidUpdate
dans votre cas, ajoutez simplement une fonction componentDidUpdate
à appeler this.drawGrid()
voici le code de travail dans JS Bin
comme je l'ai mentionné dans le code, componentDidUpdate
sera invoqué après this.setState(...)
alors componentDidUpdate
à l'intérieur va appeler this.drawGrid()
en savoir plus sur le composant Cycle de vie dans React https://facebook.github.io/react/docs/component -specs.html # update-composantwillupdate