Javascript 我可以在 setState 更新完成后执行函数吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34687091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I execute a function after setState is finished updating?
提问by monalisa717
I am very new to React JS (as in, just started today). I don't quite understand how setState works. I am combining React and Easel JS to draw a grid based on user input. Here is my JS bin: http://jsbin.com/zatula/edit?js,output
我对 React JS 很陌生(就像今天刚开始一样)。我不太明白 setState 是如何工作的。我结合 React 和 Easel JS 来根据用户输入绘制网格。这是我的 JS bin:http: //jsbin.com/zatula/edit?js, output
Here is the 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")
);
You can see in the JS bin when you change the number of rows or columns with one of the dropdowns, nothing will happen the first time. The next time you change a dropdown value, the grid will draw to the previous state's row and column values. I am guessing this is happening because my this.drawGrid() function is executing before setState is complete. Maybe there is another reason?
当您使用其中一个下拉列表更改行数或列数时,您可以在 JS bin 中看到,第一次不会发生任何事情。下次更改下拉值时,网格将绘制到前一个状态的行和列值。我猜这是因为我的 this.drawGrid() 函数在 setState 完成之前执行。也许还有其他原因?
Thanks for your time and help!
感谢您的时间和帮助!
回答by sytolk
setState(updater[, callback])
is an async function:
setState(updater[, callback])
是一个异步函数:
https://facebook.github.io/react/docs/react-component.html#setstate
https://facebook.github.io/react/docs/react-component.html#setstate
You can execute a function after setState is finishing using the second param callback
like:
您可以在 setState 完成后使用第二个参数执行函数,callback
例如:
this.setState({
someState: obj
}, () => {
this.afterSetStateFinished();
});
回答by Justin Niessner
render
will be called every time you setState
to re-render the component if there are changes. If you move your call to drawGrid
there rather than calling it in your update*
methods, you shouldn't have a problem.
render
setState
如果有更改,每次重新渲染组件时都会调用。如果您将调用移到drawGrid
那里而不是在您的update*
方法中调用它,那么您应该没有问题。
If that doesn't work for you, there is also an overload of setState
that takes a callback as a second parameter. You should be able to take advantage of that as a last resort.
如果这对您不起作用,那么还有一个setState
将回调作为第二个参数的重载。您应该能够利用它作为最后的手段。
回答by Mahdi
Making setState
return a Promise
制作setState
回报Promise
In addition to passing a callback
to setState()
method, you can wrap it around an async
function and use the then()
method -- which in some cases might produce a cleaner code:
除了传递callback
tosetState()
方法之外,您还可以将它包装在一个async
函数周围并使用该then()
方法——这在某些情况下可能会产生更清晰的代码:
(async () => new Promise(resolve => this.setState({dummy: true}), resolve)()
.then(() => { console.log('state:', this.state) });
And here you can take this one more step ahead and make a reusable setState
function that in my opinion is better than the above version:
在这里你可以更进一步,制作一个可重用的setState
函数,在我看来它比上面的版本更好:
const promiseState = async state =>
new Promise(resolve => this.setState(state, resolve));
promiseState({...})
.then(() => promiseState({...})
.then(() => {
... // other code
return promiseState({...});
})
.then(() => {...});
This works fine in React16.4, but I haven't tested it in earlier versions of Reactyet.
这在React16.4 中运行良好,但我还没有在React 的早期版本中测试它。
Also worth mentioning that keeping your callbackcode in componentDidUpdate
method is a better practice in most -- probably all, cases.
还值得一提的是,在大多数情况下(可能是所有情况),将回调代码保留在componentDidUpdate
方法中是一种更好的做法。
回答by Kennedy Yu
when new props or states being received (like you call setState
here), React will invoked some functions, which are called componentWillUpdate
and componentDidUpdate
当接收到新的 props 或状态时(就像你setState
在这里调用的那样),React 会调用一些函数,这些函数被调用componentWillUpdate
和componentDidUpdate
in your case, just simply add a componentDidUpdate
function to call this.drawGrid()
在您的情况下,只需添加一个componentDidUpdate
函数即可调用this.drawGrid()
here is working code in JS Bin
这是JS Bin 中的工作代码
as I mentioned, in the code, componentDidUpdate
will be invoked after this.setState(...)
正如我所提到的,在代码中,componentDidUpdate
将在之后调用this.setState(...)
then componentDidUpdate
inside is going to call this.drawGrid()
然后componentDidUpdate
里面会打电话this.drawGrid()
read more about component Lifecyclein React https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate
阅读有关React 中组件生命周期的更多信息https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate