本文介绍了在事件处理程序内进行setState调用后,React何时重新渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从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 a setState and will log the current props.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 for props.counter that came from the counter 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 DiscreteEvents are the ones for which this guarantee exists, and the UserBlockingEvents 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何时重新渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 02:24