Подтвердить что ты не робот

Зная, когда пользовательский интерфейс готов в React/Redux

Я хотел бы знать, как долго мое приложение становится "готовым" для взаимодействия с ним. Временная шкала загрузки приложения включает в себя следующее:

  • Загрузка DOM.
  • Первоначальный рендер.
  • HTTP-вызовы, вызванные различными componentDidMount() s
  • Возврат HTTP-вызовов. Состояние Redux обновляется с ответами HTTP.
  • React отображает новые значения из ответов HTTP.
  • Вся начальная загрузка завершена. Пользователь готов к взаимодействию с приложением.

В конце этого процесса я хочу запустить событие отслеживания, чтобы записать значение window.performance.now().

Я не уверен, что лучший способ сделать это. Реагирующая система компонентов отлично справляется с развязкой различных частей пользовательского интерфейса. В этом случае это, к сожалению, означает, что у меня не будет одного простого места, чтобы проверить, "все ли сделано с новыми данными".

Вещи, которые я пробовал:

  • Посмотрите на крючок жизненного цикла React, который сообщает мне, обновляется ли какой-либо ребенок. Что-то вроде componentOrAnyChildDidUpdate(). Я не думаю, что это существует, и это может противоречить философии Реакта.
  • Взломайте крючок жизненного цикла anyChildDidUpdate() через context и сделайте каждый компонент в моем приложении либо подклассом вспомогательного абстрактного базового класса, либо обернутым в компонент более высокого порядка. Это кажется плохим, потому что context является экспериментальным API.
  • Подпишитесь в состояние Redux через store.subscribe(). Обновите состояние Redux, чтобы иметь явную запись о возврате всех HTTP-вызовов. После того, как все HTTP-вызовы вернулись, и React завершит повторную визуализацию, я знаю, чтобы запустить обратный вызов отслеживания. Проблема заключается в том, что когда React завершает повторный рендеринг. Он работал бы, если бы мой store.subscribe() обратный вызов гарантированно выполнялся синхронно после обратного вызова react-redux. Но это не так.

Есть ли хороший способ сделать это в React?

4b9b3361

Ответ 1

Я боюсь, что в React нет универсально хорошего способа сделать это, это "логика", связанная со структурой вашего приложения.

Я хотел отобразить загрузчик при навигации с одной страницы на другую в приложении с одной страницей (SPA), написанном в ответ, и я столкнулся с аналогичной проблемой, не зная, когда прекратить ее отображение, и если все компоненты на новой странице завершены их API-вызовы/рендеринг.

Я решил, что это было:

1) Я удалил все мои вызовы API изнутри моих компонентов.

2) Создайте компонент страницы, чтобы обернуть все компоненты, включенные в эту страницу (вызывается вашим реагирующим маршрутизатором).

3) Выполняйте все запросы, требуемые для ваших компонентов одновременно при навигации (в моем случае при отображении загрузчика). Для каждого завершаемого запроса создайте обещание и внутри него динамически создайте свой компонент, используя React.createElement. Передайте компонент, созданный ответ запроса, и обработчик обещаний в качестве реквизита.

4) Разрешите обещание в компоненте componentDidMount.

5) После того, как все promises разрешены, вы знаете, что "страница" готова, и вы можете записать значение window.performance.now().

Трудно представить пример минимального кода без большого количества контекстного кода, так как этот код распространяется по всему приложению.

Ответ 2

Есть более чем один способ сделать то, что вы просите, но с моей головы я бы сделал следующее:

• Создайте перфекционный редуктор и вызовите performance.now() прямо перед тем, как я сделаю хранилище редукции и добавлю значение в начальное состояние.

{ perf: { start: '...', end: '...' } }

• Отслеживать статус загрузки начальных HTTP-запросов в загруженном редукторе.

{ loaded: { request1: false, request2: false, request3: false } }

• Подключите компонент верхнего уровня к загруженному редуктору и проверьте, завершены ли все запросы в компонентеDidUpdate. Если true, добавьте конечное значение в первичную редукцию.

import React from 'react';
import { connect } from 'react-redux';

class App extends React.Component {
  componentDidUpdate(prevProps) {
    if (!prevProps.loadingComplete && this.props.loadingComplete) {
      this.props.updatePerf(performance.now());
    }
  }
}

const mapStateToProps = state => ({
  loadingComplete: state.loaded.every(item => item),
});

const mapDispatchToProps = dispatch => ({
  updatePerf(time) {
    dispatch({ type: 'SET_ENDING_PERF', payload: time });
  },
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

Ответ 3

В нашем проекте мы используем redux и пару действий - триггер, запрос, успех, ошибку.

"Триггер" вызывает запрос и бросает загрузку: true в наш "умный" компонент "Запрос" извлекает данные и передает их в "Успех/Ошибка" "Успех", говорит нам, что все в порядке и данные загружены и бросают {loading: false, data}

В случае успеха/ошибки мы всегда знаем, что происходит с нашим приложением

И, конечно, вы можете использовать componentWillReceiveProps (nextProps) {} и проверять флаг загрузки и данные в своем компоненте

Ответ 4

Вы можете попробовать использовать react-addons-perf

Как я обычно тестирую свои приложения:

В основном вы хотите начать измерение, когда ваш компонент начнет обновление и прекратит измерение после метода жизненного цикла componentDidUpdate().

import Perf from 'react-addons-perf'

componentWillMount() {
  window.performance.mark('My app');
 }
componentDidMount() {
  console.log(window.performance.now('My app'));
  Perf.start()
  // ... do your HTTP requests
}
componentDidUpdate() {
 Perf.stop();
 Perf.printInclusive();
}

Подобно этому вы будете отслеживать исходный рендер вашего компонента + обновления вашего компонента.

Надеюсь, что это поможет

Ответ 5

Два шага для этого.

Отслеживать все HTTP-запросы с помощью действий

Простой счетчик в состоянии редукции будет достаточным, что увеличивается при запуске запроса и уменьшается на успех или неудачу (все с помощью соответствующих действий). Нет window.dirty.stuff здесь перед Дэн Абрамовым.

Отслеживать все компоненты connect ed

componentDidUpdate указывает, что все дети закончили рендеринг. Это может быть достигнуто без большого шаблона с recompose lifecycle HOC. Правильное место для повторного рендеринга отслеживания может быть sCU или просто cWRP, если вы уже используете recompose shouldUpdate или reselect, поскольку мы не будем отслеживать компоненты, которые не обновлялись.

Обратите внимание, что все принимают идиоматическое приложение action/redux, никаких сложных побочных эффектов или анимаций. Например, если какой-либо дочерний компонент где-то глубоко в иерархии запускает свой собственный запрос AJAX, скажем, на cDM, а не через действие redux. Таким образом, вы должны отслеживать их тоже, НО никто не может быть уверен, что они подразумевают какие-либо повторные визуализации. Отслеживание такого поведения по-прежнему возможно, просто потребуется больше усилий.

Ответ 6

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

например, позднее вы можете разрешить пользователю взаимодействовать с какой-то частью вашего пользовательского интерфейса, пока некоторые другие части по-прежнему загружаются, или вы можете решить, что некоторые компоненты должны позволить пользователю взаимодействовать до того, как модель данных будет готова, и т.д., другими словами, он отвечает (реагирует) на то, чтобы сказать, готов ли он/когда он готов или нет, и никто другой.

Таким образом, все "готовые" компоненты могут выставлять onLoad-подобную опору для передачи дерева реакции; корневой компонент затем будет координировать результат, изменив поток дерева вниз соответствующим образом, распространив соответствующие реквизиты до листьев.

Это может быть реализовано путем написания компонента mixin/high order для инкапсуляции логики обновления готовности.