当前位置: 首页 > 面试题库 >

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

厍华清
2023-03-14
问题内容

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

问题答案:

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

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

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

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



 类似资料:
  • 事件摘要: 我单击编辑按钮。 editForm()使用此.setState()和render()中的此.state显示表单。 上面的setState()将{this.state}作为我需要显示的值。 一旦我在表单中单击更新按钮,updateMessage()将激活,哪个Meteor.call包含回调选项。 这个回调函数有一个.setState()连接到我上面提到的{This.state}。 那么如

  • 我在本地玩axon服务器。我正在本地计算机上通过命令运行一个docker容器。 当我启动spring-boot应用程序时,聚合外部的事件处理程序会重新运行所有以前的事件,因此在启动时会看到日志语句流。 注释似乎并不能阻止这种情况。此外,我试图按照这里的说明使处理程序成为事件处理器,但要么我做得不对,要么也没有解决问题。

  • 我将一些事件转发给Kafka并启动了我的Kafka流程序。我的程序开始处理事件并完成。一段时间后,我停止了我的Kafka流应用程序并重新开始。观察到我的Kafka流程序正在处理已经处理过的先前事件。 根据我的理解,Kafka流在内部维护每个应用程序id的输入主题本身的偏移量。但在这里重新处理已经处理的事件。 如何验证Kafka流处理的偏移量?Kafka流是如何保存这些书签的?根据什么 如果Kafk

  • 有没有办法让React组件中定义的事件处理程序在类似HTML的标记中可以访问?我的意思是: 我的目标是定义,但目前我只知道如何创建诸如和之类的参数。 如何使事件处理程序通过TSX访问,类似于使用事件?

  • 问题内容: 由于某些原因,此值在反应事件处理程序中丢失。阅读我认为有反应的文档在这里做了一些工作,以确保将其设置为正确的值 以下内容不符合我的预期 但这确实是: React和ES6对我来说是新手,但这似乎不是正确的行为? 问题答案: 如果使用新语法,这对于JavaScript和React是正确的行为。 自动绑定功能不适用于 v0.13.0中的ES6类。 因此,您需要使用: 或其他技巧之一: