问题描述
从React DOCS:
From React DOCS:
https://reactjs.org/docs/state-and-lifecycle.html
React可以将多个setState()调用批处理为一个更新,以提高性能.
React may batch multiple setState() calls into a single update for performance.
这很有道理.如果您具有类似以下功能的内容,则在每次 setState
调用
This makes total sense. If you have something like the function below, it would be very inefficient to re-render on every setState
call
const [state1,setState1] = useState(false);
const [state2,setState2] = useState(false);
const [state3,setState3] = useState(false);
function handleClick() {
setState1(true);
setState2(true);
setState3(true);
}
因此,在上述情况下,我期望React将所有3个 setState
调用批处理为单个重新渲染.确实做到了!
So, in the situation above, I expect React to batch all 3 setState
calls into a single re-render. And it does exactly that!
但是我想知道的是:
handleClick
完成后,是否保证立即 handleClick
完成重新渲染?我的意思是立即立即开始,就像立即同步一样?
Once handleClick
has completed, is a re-render guaranteed to happen immediatelly handleClick
has done running? I mean literally immediately, like synchronously immediately?
从我构建的该代码段来看,这似乎是对的. handleClick
完成后,React将同步应用更新(重新渲染).如果我猜错了,请纠正我.
From this snippet that I've build, it seems that this is true. React will synchronously apply the updates (re-render) after handleClick
has completed. Correct me if I'm wrong in assuming that.
请参见下面的代码段
- 最快点击3遍
-
handleClick
将调用setState
,并将记录当前props.counter
-
App
上存在一个昂贵的循环,因此重新渲染将花费很长时间 - 您将能够以比React重新呈现整个应用程序的速度更快的速度单击
- 但是您会发现
props.counter
每次都不同,没有任何重复,即使您快速单击多次也是如此 - 这意味着处理完第二次点击(由于昂贵的循环会花一些时间)后,React已经重新渲染了整个内容,并且
handleClick
函数已经用来自counter
更新状态的props.counter
的新值. - 尝试快速单击5次,您会发现行为是相同的.
- Click 3 times as fast as you can
handleClick
will call asetState
and will log the currentprops.counter
- There is an expensive loop on
App
, so it will take a long time to re-render - You'll be able to click much faster than React can re-render the whole App
- But you'll see the
props.counter
is different every time, without any repetition, even if you click multiple times really fast - It means that once your 2nd click is processed (it will take a while because of the expensive loop), React has already re-rendered the whole thing and the
handleClick
function has already been recreated with the new value forprops.counter
that came from thecounter
updated state. - Try clicking 5 times really fast and you'll see that the behavior is the same.
问题
当在事件处理程序函数内进行 setState
调用时,一旦该处理程序函数完成运行,是否可以保证在处理程序完成后立即(同步)进行重新渲染?
When setState
calls are made inside an event handler function, once that handler function has completed running, is it guaranteed that a re-render will occur immediately (synchronously) after that completion of the handler?
function App() {
console.log("App rendering...");
const [counter, setCounter] = React.useState(0);
// AN EXPENSIVE LOOP TO SLOW DOWN THE RENDER OF 'App'
for (let i = 0; i < 100000; ) {
for (let j = 0; j < 10000; j++) {}
i = i + 1;
}
return <Child counter={counter} setCounter={setCounter} />;
}
function Child(props) {
console.log("Child rendering...");
// THIS FUNCTION WILL CALL 'setState'
// AND WILL ALSO LOG THE CURRENT 'props.counter'
function handleClick() {
props.setCounter(prevState => prevState + 1);
console.log(props.counter);
}
return (
<React.Fragment>
<div>Counter: {props.counter}</div>
<button onClick={handleClick}>Click</button>
</React.Fragment>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
推荐答案
对于某些事件,包括 click
,React保证在另一个事件发生之前会重新渲染组件.(对于其他事件,例如 mousemove
则不是这种情况.)您可以找到哪些事件是哪些此处.当前的术语似乎是 DiscreteEvent
s是此保证存在的术语,而 UserBlockingEvent
s是其不保证保证的术语.在当前的实现中,很可能意味着它是在事件处理结束时同步完成的,¹但我认为保证并不那么具体.
For certain events, including click
, React guarantees that the component will be re-rendered before another event can occur. (This isn't the case for other events like mousemove
.) You can find which events are which here. The current terminology seems to be that DiscreteEvent
s are the ones for which this guarantee exists, and the UserBlockingEvent
s are the ones for which it isn't guaranteed. It may well be that in the current implementation that means it's done synchronously at the end of the event handling¹, but I think the guarantee is less specific than that.
我是从Dan Abramov 在Twitter上(他在事件中使用了较旧的术语).
I learned this from Dan Abramov on Twitter (he used the older terminology for the events).
¹实际上,在他的答案中,约瑟夫·D.指向丹·阿布拉莫夫(Aan Abramov)的评论表示,目前是,但还说"实施细节,并可能在将来的版本中更改..
¹ and in fact, in his answer Joseph D. points to a comment by Dan Abramov saying that it is, for now, but also saying "This is implementation detail and may change in future versions".
这篇关于在事件处理程序内进行setState调用后,React何时重新渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!