小编典典

在事件处理程序内进行setState调用后,React何时重新渲染

reactjs

从React DOCS:

https://reactjs.org/docs/state-and-
lifecycle.html

状态更新可能是异步的

React可以将多个setState()调用批处理到单个更新中以提高性能。

这是完全合理的。如果您具有类似下面的功能,则在每次setState调用时重新渲染效率很低

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调用分批处理成一个单独的重新渲染。而它确实做到了!

但是我想知道的是:

一旦handleClick完成,正在重新绘制一定会发生的 immediatelly
handleClick做跑步?我的意思是立即立即,就像立即同步一样?

从我构建的这段代码来看,这似乎是对的。完成后,React将 同步 应用更新(重新渲染)handleClick。如果我认为不对,请纠正我。

请参见下面的代码段:

  • 单击速度尽可能快3倍
  • handleClick将调用a setState并记录当前props.counter
  • 上有一个昂贵的循环App,因此重新渲染将花费很长时间
  • 您能够以比React可以重新渲染整个App更快的速度单击
  • 但是props.counter,即使您多次快速单击,您也会看到每次都不同,没有任何重复
  • 这意味着一旦处理完第二次点击(由于昂贵的循环,将需要一段时间),React已经重新渲染了整个内容,并且handleClick已经使用props.counter来自counter更新状态的新值重新创建了功能。
  • 尝试快速单击5次,您会发现行为是相同的。

setState在事件处理程序函数内进行调用时,一旦该处理程序函数完成运行,是否可以保证在处理程序完成后立即(同步)进行重新渲染?

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"/>

阅读 235

收藏
2020-07-22

共1个答案

小编典典

一旦handleClick完成,正在重新绘制一定会发生的immediatelly
handleClick做跑步?我的意思是立即立即开始,就像立即同步

对于某些事件,包括click,React保证在另一个事件发生之前会重新渲染组件。(对于其他事件,情况并非如此mousemove。)您可以在此处找到哪些事件。当前的术语似乎是DiscreteEvents是保证存在的术语,而UserBlockingEvents是不保证存在的术语。在当前的实现中,很可能意味着它是在事件处理结束时同步完成的¹,但我认为保证并不那么具体。

在Twitter上从Dan
Abramov那里学到了这一点(他在活动中使用了较旧的术语)。


¹编辑:而事实上,在他的回答约瑟夫D.点,由丹阿布拉莫夫评论说,这是,现在,也说
:“这是实现细节,并在未来的版本可能会改变”

2020-07-22