Как избежать предупреждений о контрольной сумме разметки React во время рендеринга

При использовании изоморфного рендеринга для компонента React, отображающего время, я иногда сталкиваюсь с проблемой, когда сервер отображает время в точке A, но к тому времени, когда клиент выбирает SPA, время от точки A изменилось до точки B, и React выдает предупреждение React attempted to reuse markup in a container but the checksum was invalid:

введите здесь описание изображения

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

Есть ли способ эффективно сообщить React на стороне клиента: "Все в порядке, эта небольшая часть DOM здесь может отличаться от серверной"? Или, может быть, есть другой способ, о котором я не подумал?

Подробнее

Я использую компонент React-Intl FormattedRelative для отображения даты создания элемента в удобном мода. Дата создания элемента, конечно, остается одинаковой между клиентом и сервером (и передается клиенту в сериализованном хранилище Flux), но разница во времени рендеринга сервера и клиента достаточно велика, чтобы отображаемый HTML часто — но не всегда — отличается.


person Collin Allen    schedule 27.07.2015    source источник
comment
Вам просто нужно убедиться, что ваш первоначальный вызов рендеринга на стороне клиента имеет ТОЧНО те же данные, что и рендеринг на стороне сервера. Это различие данных - единственный способ возникновения ошибки контрольной суммы. Поэтому всегда выполняйте рендеринг на стороне клиента с моментальным снимком данных с сервера, а затем подключайтесь к любым изменениям данных, которые могли произойти ПОСЛЕ первоначального рендеринга.   -  person Mike Driver    schedule 28.07.2015
comment
Я знаю, почему это происходит, но я визуализирую то, что по своей сути прогрессирует. Ошибка возникает между моментом завершения рендеринга сервером и завершением рендеринга клиентом.   -  person Collin Allen    schedule 28.07.2015
comment
Хорошо, вам нужно сделать что-то, игнорируя тот факт, что ваши данные меняются для этого первоначального рендеринга клиента, даже если они неверны. В противном случае вы будете продолжать видеть эту ошибку. Способы, которыми я обходил это в прошлом, например, при использовании Flux, я инициализирую хранилища потоков на стороне клиента на основе данных json, отправленных на странице html с сервера, которые точно соответствуют структуре данных, используемой для рендеринга на стороне сервера. Я визуализирую один раз с этими данными, а затем загружаю остальные соединения API.   -  person Mike Driver    schedule 28.07.2015
comment
Конечно, ваш другой вариант НЕ состоит в том, чтобы отображать серверные компоненты на основе частей ваших данных, которые прогрессируют. Возможно, сначала рендеринг состояния загрузки с сервера для соответствующих компонентов, а затем загрузка этих данных только со стороны клиента.   -  person Mike Driver    schedule 28.07.2015
comment
Я использую Flux (через Marty.js), и данные, которые я отображаю, представляют собой набор объектов Date, поступающих из хранилища, обезвоженного сервером и повторно гидратированного клиентом, но проблема возникает, потому что то, что возвращает render(), отличается с течением времени. .   -  person Collin Allen    schedule 28.07.2015
comment
Правильно, но данные при рендеринге могут отличаться, но не первоначальный рендеринг на стороне клиента.   -  person Mike Driver    schedule 28.07.2015


Ответы (2)


Это было исправлено в React Intl v2. Он добавляет свойство initialNow для стабилизации времени рендеринга.

В React Intl v2 для экземпляров <FormattedRelative> была добавлена ​​новая функция, теперь они «тикают» и остаются в актуальном состоянии. Так как время движется вперед, было непонятно, что имя объекта сейчас, поэтому оно было переименовано в initialNow. Любые экземпляры <FormattedRelative>, которые используются сейчас, должны изменить имя свойства на initialNow:

Использование:

<FormattedRelative value={date} initialNow={Date.now()}/>

Вы также можете предоставить это на IntlProvider, и в этом случае все экземпляры FormattedRelative будут стабилизированы.

Примечание. Компонент <IntlProvider> также имеет реквизит initialNow, которому можно присвоить значение для стабилизации опорного времени «сейчас» для всех экземпляров <FormattedRelative>. Это полезно для универсальных/изоморфных приложений для правильной контрольной суммы React между начальным рендерингом сервера и клиента.

Использование:

<IntlProvider initialNow={Date.now()}>
  <FormattedRelative value={date}/>
</IntlProvider>

Ссылка: https://github.com/yahoo/react-intl/wiki/Upgrade-Guide#update-how-relative-times-are-formatted

person Mrchief    schedule 14.07.2017

Поскольку данные будут меняться, как только они будут отображаться на стороне клиента, нет смысла отображать этот фрагмент на стороне сервера.

Так что сделайте небольшой компонент, который отрисовывает эту часть информации, но только с помощью force_update после монтирования.

Перед монтированием просто поместите все, что вы хотите, чтобы пользователь увидел за мгновение до завершения рендеринга.

person Mitch VanDuyn    schedule 26.01.2016