为什么在状态更新之前通过setTimeout评估三元运算符的不可达部分?

问题描述 投票:0回答:2

我有以下代码,这是一个反应组件呈现一个巨大的组件。只要巨大的组件没有完成渲染,就会显示一个加载指示器。

import * as React from "react";
import ReactDOM from "react-dom";

import {HUGEComponent} from "./huge.tsx";

class App extends React.Component<{}, {loading: boolean}> {
  constructor(props: {}) {
    super(props);
    this.state = {loading: true};
  }

  componentDidMount() {
    setTimeout(() => this.setState({loading: false}), 0);
  }

  render() {
    return this.state.loading ? <p>Loading...</p> : <HUGEComponent />;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

setTimeout内部的componentDidMount函数确保状态更新仅在加载HUGEComponent之后才发生(我使用10000段lorem ipsum作为HUGEComponent)。如果没有setTimeout,状态会立即更新,并且不会显示加载指示器。

所以我的问题是,为什么这与setTimeout一起工作?我知道,它将状态更新推送到消息队列,因此将在所有其他内容完成后执行。但是因为使用了三元运算符(延迟求值),所以HUGEComponent的实际渲染应该等到状态更新,以便在渲染之前进行状态更新,但这似乎不正确。只要没有评估<HUGEComponent />,该州实际上没有更新。那么为什么<HUGEComponent />在状态更新之前进行了评估,尽管三元运算符中存在惰性评估?

javascript reactjs settimeout jsx ternary-operator
2个回答
1
投票

我认为你对事件的解释是错误的。实际上状态更新并不等待HugeComponent进行评估,但它会立即发生,触发重新渲染并导致HugeComponent进行评估。当HugeComponent正在评估时,你不会看到你的DOM有任何变化,所以这就是在HugeComponent评估时加载文本的原因。

对于不使用setTimeout的情况,@ tan-dat的回答是有意义的。如果未使用setTimeout,则用户将看不到中间状态(这是您的加载文本)。


0
投票

也许是因为这个。

您可以在componentDidMount()中立即调用setState()。它将触发额外的渲染,但它会在浏览器更新屏幕之前发生。这保证了即使在这种情况下将调用render()两次,用户也不会看到中间状态。请谨慎使用此模式,因为它通常会导致性能问题。在大多数情况下,您应该能够在构造函数()中分配初始状态。但是,当您需要在渲染依赖于其大小或位置的内容之前测量DOM节点时,可能需要对模态和工具提示等情况进行处理。 React docs

类似的问题可以解释原因:Is setState() inside componentDidMount() considered an anti-pattern

© www.soinside.com 2019 - 2024. All rights reserved.