Jestem bardzo nowy w React JS (tak jak w, dopiero dzisiaj zacząłem). Nie do końca rozumiem, jak działa setState. Łączę React i Easel JS, aby narysować siatkę na podstawie danych wejściowych użytkownika. Oto mój bin JS: http://jsbin.com/zatula/edit?js,output
Oto kod:
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")
);
Możesz zobaczyć w koszu JS, gdy zmienisz liczbę wierszy lub kolumn za pomocą jednego z menu rozwijanych, nic się nie stanie za pierwszym razem. Następnym razem, gdy zmienisz wartość listy rozwijanej, siatka zostanie narysowana do wartości wierszy i kolumn poprzedniego stanu. Domyślam się, że to się dzieje, ponieważ moja funkcja this.drawGrid () jest wykonywana przed zakończeniem setState. Może jest inny powód?
Dziękuję za poświęcony czas i pomoc!
źródło
this.drawGrid()
wcomponentDidUpdate
jak @kennedyyu zasugerował, ponieważ za każdym razemsetState
jest zakończone, będę chciał przerysować siatkę (tak byłoby to zaoszczędzić kilka linii kodu), ale osiągnąć to samo .render
zostanie wywołana za każdym razem, gdy będzieszsetState
ponownie renderować komponent, jeśli nastąpią zmiany. Jeśli przenosisz tam swoje wywołaniedrawGrid
zamiast wywoływać je w swoichupdate*
metodach, nie powinieneś mieć problemu.Jeśli to nie zadziała, istnieje również przeciążenie,
setState
które pobiera wywołanie zwrotne jako drugi parametr. Powinieneś mieć możliwość skorzystania z tego w ostateczności.źródło
render: function() { this.drawGrid(); return......
render()
... odpowiedź sytolk powinna być akceptowanasetState
powinno być używane w ostateczności. Zgadzam się z większością obecnych tutaj ludzi, że warto zastosować takie podejście.react
vdom by dbać o nie robi zbyt wiele pracy w większości przypadków jest to współdziałanie z inną biblioteką chcesz zminimalizowaćDokonywanie
setState
zwrotu aPromise
Oprócz przekazania metody
callback
dosetState()
, możesz owinąć ją wokółasync
funkcji i użyćthen()
metody - co w niektórych przypadkach może dać bardziej przejrzysty kod:I tutaj możesz zrobić kolejny krok do przodu i zrobić funkcję wielokrotnego użytku,
setState
która moim zdaniem jest lepsza niż powyższa wersja:Działa to dobrze w React 16.4, ale nie testowałem tego we wcześniejszych wersjach Reacta .
Warto również wspomnieć, że przechowywanie kodu wywołania zwrotnego w
componentDidUpdate
metodzie jest lepszą praktyką w większości - prawdopodobnie we wszystkich przypadkach.źródło
gdy otrzymywane są nowe właściwości lub stany (jak to nazywasz
setState
tutaj), React wywoła pewne funkcje, które są wywoływanecomponentWillUpdate
icomponentDidUpdate
w twoim przypadku po prostu dodaj
componentDidUpdate
funkcję do wywołaniathis.drawGrid()
tutaj działa kod w JS Bin
jak wspomniałem w kodzie,
componentDidUpdate
zostanie wywołany późniejthis.setState(...)
wtedy w
componentDidUpdate
środku zadzwonithis.drawGrid()
przeczytaj więcej o cyklu życia komponentów w React https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate
źródło