We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
让我们先从一道典型面试题开始:
class Test extends Component { state = { count: 0 } componentDidMount(){ this.setState({ count: this.state.count + 1 }); console.log(this.state.count); setTimeout(() => { this.setState({ count: this.state.count + 1 }); console.log("setTimeout: " + this.state.count); }, 0); } render(){ ... } }
上面代码打印结果是什么?
如果你认为setState是异步的,所以这里应该打印0,0
setState
这样是错的。
正确答案应该是0,2
要知道为什么,就要理解React中的合成事件。因为在合成事件中触发的setState才是异步的,而在合成事件之外触发的就是同步的。
大家都知道事件委托,合成事件也是如此:
那么哪些事件才能被React捕获生成合成事件呢?
下面的测试快照罗列了可以被React捕获生成合成事件的事件:
// react/packages/react-dom/src/__tests__/__snapshots__/ReactTestUtils-test.js.snap Array [ "abort", "animationEnd", "animationIteration", "animationStart", "auxClick", "beforeInput", "blur", "canPlay", "canPlayThrough", "cancel", "change", "click", "close", "compositionEnd", "compositionStart", "compositionUpdate", "contextMenu", "copy", "cut", "doubleClick", "drag", "dragEnd", "dragEnter", "dragExit", "dragLeave", "dragOver", "dragStart", "drop", "durationChange", "emptied", "encrypted", "ended", "error", "focus", "gotPointerCapture", "input", "invalid", "keyDown", "keyPress", "keyUp", "load", "loadStart", "loadedData", "loadedMetadata", "lostPointerCapture", "mouseDown", "mouseEnter", "mouseLeave", "mouseMove", "mouseOut", "mouseOver", "mouseUp", "paste", "pause", "play", "playing", "pointerCancel", "pointerDown", "pointerEnter", "pointerLeave", "pointerMove", "pointerOut", "pointerOver", "pointerUp", "progress", "rateChange", "reset", "scroll", "seeked", "seeking", "select", "stalled", "submit", "suspend", "timeUpdate", "toggle", "touchCancel", "touchEnd", "touchMove", "touchStart", "transitionEnd", "volumeChange", "waiting", "wheel", ]
由此我们看到,addEventListener和setTimeout、setInterval等原生事件并不在此列,所以,这些原生事件中触发的setState就是同步的。
addEventListener
setTimeout
setInterval
其实,在React源码中,会有一个变量标记state应该同步更新还是异步更新,这个变量就是isBatchingUpdates。如果为true,就是异步更新,反之则是同步更新。
isBatchingUpdates
那为什么要有异步更新呢?
2017年的时候就已经有人问过这个问题,官方回答主要提到了以下两个点:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
让我们先从一道典型面试题开始:
上面代码打印结果是什么?
如果你认为
setState
是异步的,所以这里应该打印0,0这样是错的。
正确答案应该是0,2
要知道为什么,就要理解React中的合成事件。因为在合成事件中触发的
setState
才是异步的,而在合成事件之外触发的就是同步的。合成事件
大家都知道事件委托,合成事件也是如此:
那么哪些事件才能被React捕获生成合成事件呢?
下面的测试快照罗列了可以被React捕获生成合成事件的事件:
由此我们看到,
addEventListener
和setTimeout
、setInterval
等原生事件并不在此列,所以,这些原生事件中触发的setState
就是同步的。其实,在React源码中,会有一个变量标记state应该同步更新还是异步更新,这个变量就是
isBatchingUpdates
。如果为true,就是异步更新,反之则是同步更新。那为什么要有异步更新呢?
2017年的时候就已经有人问过这个问题,官方回答主要提到了以下两个点:
setState
时根据来源不同分配不同的优先级,再根据优先级并发处理,提升渲染性能。The text was updated successfully, but these errors were encountered: