Почему событие api браузера подписано в componentDidMount в React?
В этом выступлении https://reactjs.org/docs/hooks-intro.html докладчик пишет коды, которые выглядят примерно так:
class SomeComponent extends React.Component {
constructor(props){
super(props)
this.handleResize.bind(this)
}
handleResize(){
//do something with window.innerWidth
}
componentDidMount(){
window.addEventListener('resize',this.handleResize)
}
}
Почему window.addEventListener
часть в componentDidMount? Так должно быть?
По тону разговора я почувствовал, что это довольно обычная ситуация.
Я новичок, чтобы реагировать, и я бы также поместил подписку на событие api браузера в конструкторе.
Есть ли какое-либо преимущество, которое могло бы ускользнуть от того, почему это window.addEventListener
в componentDidMount? Или это оправдано для удобства чтения?
4 ответа
Для меня это довольно просто.
Во-первых, вы хотите, чтобы вызовы API или прослушиватели событий вызывались / инициализировались только один раз,componentDidMount()
а также constructor
гарантированно запускается только один раз для каждого установленного компонента.
Однако я не буду помещать api в конструктор, потому что, если вы хотите обновить пользовательский интерфейс после того, как ваши данные будут возвращены из api, вампотребуется изменение состояния, в то время как вы не можете установить состояние вconstructor
. Единственное место, которое запускается только один раз и позволяет установить состояние, - этоcomponentDidMount()
.
Для слушателей событий я думаю, что это можно вставить constructor
/componentDidMount
. Однако официальные документы рекомендуют, чтобыcomponentDidMount()
. Посмотри на это.
componentDidMount вызывается после монтирования компонента и имеет представление DOM. Часто это место, куда вы присоединяете общие события DOM.
В целом конструкторы не должны иметь побочных эффектов.
А также в документации React уже упоминалось об этом:
Избегайте использования каких-либо побочных эффектов или подписок в конструкторе. В таких случаях используйте вместо него componentDidMount().
В window.addEventListener
определить в componentDidMount
жизненный цикл, потому что код определен внутри componentDidMount
выполняется после рендеринга DOM. И это был бы подходящий момент, чтобы попытаться прикрепить любой обработчик событий к элементу, который является частью DOM.
Но если вы сделали это внутри конструктора, есть много шансов, что он будет вызван до того, как DOM будет полностью отрисован.
Есть несколько причин componentDidMount()
На практике, componentDidMount
это лучшее место для размещения вызовов для получения данных по нескольким причинам.
1- Если вы хотите подписаться и отписаться от своей функции, вам необходимо вызвать эту функцию в componentDidMount()
и отписаться (после всех операций) позвонить в componentWillUnmount()
2-Использование didMount дает понять, что данные не будут загружены до завершения первоначального рендеринга. Это напоминает вам о необходимости правильно настроить начальное состояние, чтобы вы не получили неопределенное состояние, которое вызывает ошибки.
3-componentDidMount()
метод жизненного цикла вызывается после render()
чтобы обеспечить успешную загрузку DOM.
window.addEventListener('resize',this.handleResize)=> Вы также можете вызвать конструктор, но позже, если вам нужно отказаться от подписки, этого не сделать, потому что это начальная фаза (вызывается только изначально).