Почему недоступная часть троичного оператора оценивается до обновления состояния через setTimeout? - PullRequest
0 голосов
/ 10 марта 2019

У меня есть следующий код, который является компонентом реакции, который рендерит огромный компонент. Пока огромный компонент не закончил рендеринг, отображается индикатор загрузки.

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 /> оценивается до обновления состояния, несмотря на ленивую оценку в троичном операторе?

Ответы [ 2 ]

1 голос
/ 10 марта 2019

Я думаю, что ваша интерпретация событий неверна.На самом деле обновление состояния не ожидает оценки HugeComponent, но происходит немедленно, что вызывает повторное отображение и вызывает оценку HugeComponent.Пока HugeComponent выполняет оценку, вы не увидите никаких изменений в DOM, поэтому это делает загрузку текста видимой, пока HugeComponent выполняет оценку.

Для случая, когда setTimeout не используется, ответ @ tan-dat имеет смысл,Когда setTimeout не используется, пользователь не увидит промежуточное состояние (которое является загрузочным текстом).

0 голосов
/ 10 марта 2019

Может быть, из-за этого.

Вы можете вызвать setState () немедленно в componentDidMount (). Это вызовет дополнительный рендеринг, но это произойдет до того, как браузер обновит экран. Это гарантирует, что даже если render () будет вызываться дважды в этом случае, пользователь не увидит промежуточное состояние. Используйте этот шаблон с осторожностью, поскольку он часто вызывает проблемы с производительностью. В большинстве случаев вы должны иметь возможность назначить начальное состояние в конструкторе (). Однако это может быть необходимо для случаев, таких как модалы и всплывающие подсказки, когда вам нужно измерить узел DOM перед рендерингом чего-либо, что зависит от его размера или положения. Реагировать на документы

Аналогичный вопрос, который может объяснить, почему: Является ли setState () внутри componentDidMount () антипаттерном

...