#reactjs #redux #react-redux
#reactjs #redux #реагировать-redux
Вопрос:
Я прочитал componentDidMount
, что он вызывается только один раз для первоначального рендеринга, но я вижу, что он отображается несколько раз.
Кажется, я создал рекурсивный цикл.
- componentDidMount отправляет действие для извлечения данных
- после получения данных он запускает успешное действие для сохранения данных в состоянии redux.
- родительский компонент react подключен к хранилищу redux и имеет
mapStateToProps
для записи, которая только что изменилась на предыдущем шаге - родитель отображает дочерние компоненты (которые программно выбираются через переменную)
- componentDidMount дочернего компонента вызывается снова
- он отправляет действие для извлечения данных
Я думаю, что это то, что происходит. Возможно, я ошибаюсь.
Как я могу остановить цикл?
Вот код для программной визуализации дочерних компонентов.
function renderSubviews({viewConfigs, viewConfig, getSubviewData}) {
return viewConfig.subviewConfigs.map((subviewConfig, index) => {
let Subview = viewConfigRegistry[subviewConfig.constructor.configName]
let subviewData = getSubviewData(subviewConfig)
const key = shortid.generate()
const subviewLayout = Object.assign({}, subviewConfig.layout, {key: key})
return (
<div
key={key}
data-grid={subviewLayout}
>
<Subview
{...subviewData}
/>
</div>
)
})
}
Ответ №1:
Экземпляр компонента будет смонтирован только один раз и размонтирован при удалении. В вашем случае он удаляется и создается заново.
Цель key
prop — помочь React найти предыдущую версию того же компонента. Таким образом, он может обновлять предыдущий компонент новыми реквизитами, а не создавать новый.
React часто может нормально работать без ключа, исключением является список с элементами. Ему нужен ключ, чтобы он мог отслеживать, когда элементы переставляются, создаются или удаляются.
В вашем случае вы явно сообщаете React, что ваш компонент отличается от предыдущего. Вы предоставляете новый ключ при каждом рендеринге. Это заставляет React обрабатывать предыдущий экземпляр как удаленный. Все дочерние элементы этого компонента также размонтируются и демонтируются.
Что вам следует сделать, так это (никогда) не генерировать ключ случайным образом. Ключи всегда должны основываться на идентификаторе данных, отображаемых компонентом. Если это не элемент списка, вам, вероятно, не нужен ключ. Если это элемент списка, гораздо лучше использовать ключ, полученный из идентификатора данных, например, свойство ID или, возможно, комбинацию нескольких полей.
Если бы генерация случайного ключа была правильной, React просто позаботился бы об этом за вас.
Вы должны поместить свой начальный код выборки в корень вашего дерева React, обычно это App
. Не помещайте его в какой-то случайный дочерний элемент. По крайней мере, вы должны поместить его в компонент, который существует в течение всего срока службы вашего приложения.
Основная причина его установки заключается в componentDidMount
том, что он не запускается на сервере, потому что компоненты на стороне сервера никогда не монтируются. Это важно для универсального рендеринга. Даже если вы не делаете этого сейчас, вы можете сделать это позже, и быть готовым к этому — лучшая практика.
Комментарии:
1. Вау, спасибо за ответ. Я вернулся, чтобы перефразировать свой вопрос, потому что то, что я спросил, было неясно, и вот ответ, который объясняет, почему это происходит. Спасибо
2. Я многому научился из этого ответа! Очень элегантный подход от react
3. Есть ли какие-либо обстоятельства, при которых компонент верхнего уровня, попадающий непосредственно по маршрутизации из адресной строки, попадет в componentDidMount более одного раза? Я почти уверен, что видел это. Если есть такой случай, есть ли способ ВНУТРИ компонента, за исключением внутреннего взлома в исходном сообщении, установить ключ компонента, чтобы, возможно, предотвратить это? Я не понимаю, почему это может произойти или должно быть необходимо. Но, возможно, я что-то упускаю.
4. Компонент будет смонтирован только один раз. Возможно, компонент был удален, а затем воссоздан заново, или, возможно, существует более одного экземпляра. React не удалит ваш компонент, но патентный компонент может.
5. Итак, я только что столкнулся с подобной ситуацией. Я видел два монтирования и никогда не отменял монтирование. Что произошло, так это то, что у меня было два маршрута, один из которых направлялся в /wizard, а другой — в /wizard/:id это привело к монтированию двух компонентов, но отображался только один. Мне было трудно отследить, почему изменения состояния отражались в отладчике в некоторых случаях, а не в других. Я удалил маршрут без параметров, и мир снова стал хорошим. Таким образом, может показаться, что компонент монтировался дважды, но на самом деле это были два отдельных экземпляра одного и того же компонента. Я не уверен, есть ли хороший способ отладить это или нет.
Ответ №2:
Множественные componentDidMount
вызовы могут быть вызваны использованием <React.StrictMode>
вокруг вашего компонента. После его удаления двойные вызовы исчезли.
Это поведение предназначено для выявления неожиданных побочных эффектов. Подробнее об этом можно прочитать в документации. Это происходит только в среде разработки, в то время как в рабочей componentDidMount
среде вызывается только один раз даже с <React.StrictMode>
.
Для вашего конкретного случая ответ DDS правильный. Однако строгий режим также является распространенной проблемой, и этот вопрос часто встречается в результатах Google.
Комментарии:
1. <comp key=»anythingunique»/> у меня не сработало. удаление строгого режима сделало свое дело!
Ответ №3:
Просто цитата:
Это просто потому, что мы делаем 2 начальных рендеринга в режиме разработки, чтобы избежать получения предупреждений о несоответствующей разметке клиент / сервер при введении devtools. Не влияет на производительность.
Первая картинка — режим разработки, вторая — режим производства.
Ответ №4:
Я испытал, что мой componentDidMount вызывается дважды. Я отлаживал свое дерево компонентов, пока не достиг корневого индекса. Затем я попытался удалить <React.StrictMode>, и это сработало. componentDidMount вызывался только один раз. Это потому, что <React.StrictMode> намеренно дважды вызывает определенные методы жизненного цикла React, включая componentDidMount , чтобы помочь обнаружить потенциальные проблемы с кодом. <React.StrictMode> предназначен для выявления потенциальных проблем, таких как побочные эффекты, и предупреждения о них во время разработки.