我是React JS的新手(就像今天刚刚开始的那样).我不太明白setState是如何工作的.我将React和Easel JS结合起来根据用户输入绘制网格.这是我的JS bin:http://jsbin.com/zatula/edit? js, output
这是代码:
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 (); } }); ReactDOM.render(Rows: { this.state.rows }
Columns: {this.state.cols }
, document.getElementById("container") );
当您使用其中一个下拉列表更改行数或列数时,您可以在JS bin中看到,第一次不会发生任何事情.下次更改下拉列值时,网格将绘制到先前状态的行和列值.我猜这发生了,因为我的this.drawGrid()函数在setState完成之前执行.也许还有另一个原因?
感谢您的时间和帮助!
setState(updater[, callback])
是一个异步函数:
https://facebook.github.io/react/docs/react-component.html#setstate
您可以在setState完成后使用第二个参数执行一个函数,callback
如:
this.setState({ someState: obj }, () => { this.afterSetStateFinished(); });
render
setState
如果有更改,每次重新渲染组件时都会调用.如果您将呼叫转移到drawGrid
那里而不是在update*
方法中调用它,那么您应该没有问题.
如果这对你不起作用,那么还有一个重载setState
会将回调作为第二个参数.你应该能够利用它作为最后的手段.
当新的道具或状态接收(如你拨打setState
这里),会做出反应调用一些功能,这是所谓的componentWillUpdate
和componentDidUpdate
在你的情况下,只需添加一个componentDidUpdate
函数来调用this.drawGrid()
这是JS Bin中的工作代码
正如我所提到的,在代码中,componentDidUpdate
将在之后调用this.setState(...)
然后componentDidUpdate
里面打电话this.drawGrid()
在React中了解有关组件生命周期的更多信息https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate
setState
回报Promise
除了传递callback
to setState()
方法之外,您还可以将其包装在async
函数周围并使用该then()
方法-在某些情况下,这可能会产生更简洁的代码:
(async () => new Promise(resolve => this.setState({dummy: true}), resolve)() .then(() => { console.log('state:', this.state) });
在这里,您可以再向前迈出一步,并提供一个可重用的setState
功能,我认为它比上述版本更好:
const promiseState = async state => new Promise(resolve => this.setState(state, resolve)); promiseState({...}) .then(() => promiseState({...}) .then(() => { ... // other code return promiseState({...}); }) .then(() => {...});
在React 16.4中可以正常工作,但是我尚未在React的早期版本中对其进行过测试。
还值得一提的是,在大多数情况下(可能是所有情况下),将回调代码保留在componentDidUpdate
方法中是一种较好的做法。