конструктор будет выполняться дважды? - Легкая реакция на строгий режим

React.js

предисловие

StrictModeдаReactсуществует16.3В версию добавлен компонент, согласно официальному заявлению:

StrictMode — это инструмент, используемый для выявления потенциальных проблем в приложении. Как и Fragment, StrictMode не отображает никакого видимого пользовательского интерфейса. Он запускает дополнительные проверки и предупреждения для своих дочерних элементов.

Я уверен, что многие люди знают столько же, сколько и яStrictModeаналогичныйJavaScriptсерединаuse strict, может позволитьReactПрограмма работает в более строгих условиях, и я использовал ее в проектах, но до сих пор мало о ней знаюStrictModeКак обнаружить проблемы с программой. Ниже приводится простое введение для всех через вопрос.StrictMode.

вопрос

Вы можете взглянуть на приведенный выше простой код и подумать о значении, которое в конечном итоге будет отображаться на странице, то естьAppкомпонентstate.idКакова будет стоимость?

я верю всемReactЕсли вы это понимаете, вы скажете это без колебанийstate.id = 1ответ, ответПроизводственная средадействительно правильный ответ, ведь вReactОфициальная документация говорит намClass ComponentизconstructorБудет выполняться только один раз во время рендеринга. но тысреда разработкиПри запуске отображается ответ не так, как мы думали, давайте хорошо проведем времярезультат работыБар:

большой2появилось на нашем экране. с чего бы это2, не так хорошоconstructorБудет ли он выполнен только один раз? ЭтоReactсолгал нам?

«Виновником» этой проблемы являетсяReact.StrictMode, который в среде разработки будетconstructorФункция вызывается дважды, а почему она вызывается дважды? На самом деле, чтобы обнаружить неожиданные побочные эффекты, некоторые скрытые побочные эффекты усиливаются путем двойного вызова, чтобы разработчики могли лучше их обнаружить. Подробности можно найти во введении ниже.

Знакомство с функцией StrictMode

1. Обнаружение неожиданных побочных эффектов

Из концепции реагировать два этапа:

Фаза рендеринга определяет, какие изменения необходимо внести, напримерDOM. На данном этапе,Reactпередачаrender, затем сравните результат с последним визуализированным результатом. Фаза фиксации происходит, когдаReactПри применении изменений. (дляReact DOM, произойдет вReactВставить, обновлять и удалятьDOMвремя узла. ) на данном этапе,Reactтакже позвонитcomponentDidMountа такжеcomponentDidUpdateметоды жизненного цикла, такие как . Фаза фиксации обычно проходит быстро, но процесс рендеринга может быть медленным. Поэтому предстоящийconcurrentРежим (не включен по умолчанию) разбивает работу по рендерингу на части, приостанавливая и возобновляя задачи, чтобы избежать блокировки браузера. это означаетReactМетоды жизненного цикла фазы рендеринга могут вызываться несколько раз перед фиксацией или без фиксации (из-за ошибки или задачи с более высоким приоритетом, прерывающей ее).

Жизненный цикл фазы рендеринга включает следующие методы компонента класса:

- constructor
- componentWillMount (or UNSAFE_componentWillMount)
- componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
- componentWillUpdate (or UNSAFE_componentWillUpdate)
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- setState 更新函数(第一个参数)

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

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

- class 组件的 constructor 方法
- render 方法
- setState 更新函数 (第一个参数)
- 静态的 getDerivedStateFromProps 生命周期方法

Все вышеперечисленные слова происходят отReactизОфициальная китайская документация, потому что в документации уже указано, чтоStrictModeЗачем нам нужно обнаруживать неожиданные побочные эффекты и как обнаруживать неожиданные побочные эффекты?

кrenderМетод в качестве примера, просто посмотрите наStrictModeРеализация обнаружения непреднамеренных побочных эффектов:

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

2. Определите небезопасные жизненные циклы

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

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

StrictModeЭто может помочь нам определить, используются ли эти небезопасные методы жизненного цикла в нашем коде. После того, как создание экземпляра компонента класса будет завершено, он перейдет к экземпляру компонента, чтобы узнать, есть ли какие-либоcomponentWillMountилиUNSAFE_componentWillMountНекоторые из этих небезопасных методов жизненного цикла помещаются в массив, и, наконец, на консоль выдается предупреждение. Реализация кода относительно проста, можете посмотреть, если интересноReactStrictModeWarnings.jsсерединаrecordUnsafeLifecycleWarningsа такжеflushPendingUnsafeLifecycleWarningsэти два метода.

3. Предупреждение об использовании устаревшего метода findDOMNode.

Reactдля поддержкиfindDOMNodeвойти в данныйclassискать в дереве без экземпляраDOMузел. Обычно вам не нужно этого делать, потому что вы можете поставитьrefсвязываться непосредственно сDOMузел.

findDOMNodeтакже может использоваться дляclassкомпонент, но это нарушает принцип абстракции, это заставляет родительский компонент отдельно отображать дочерний компонент. Это создает опасность рефакторинга, вы не можете изменить детали реализации компонента, потому что родительский компонент может получить доступ к егоDOMузел.findDOMNodeвозвращает только первый дочерний узел, но используйтеFragments, компонент может отображать несколькоDOMузел.findDOMNodeявляется однократным API только для чтения. Вызов этого метода вернет только результаты первого запроса. Это изменение невозможно отследить, если дочерний компонент отображает другой узел. следовательно,findDOMNodeтолько если компонент возвращает одно и неизменноеDOMДействует только для узлов.

Этот отрывок тоже из официальной документации, т.к.findDOMNodeэти проблемы, поэтомуReactпринять решениеStrictModeсбросить его при вызовеfindDOMNodeОн определит, находится ли он в режиме StrictMode, и если да, выведет предупреждение на консоль.

4. Обнаружение устаревших контекстных API

потому что старыйContext APIКогда значение контекста обновляется, нет никакого способа гарантировать, что все дочерние узлы могут быть обновлены (поскольку промежуточный родительский компонентshouldComponentUpdateвернутьfalse, то компоненты-потомки, использующие это значение, не будут обновляться), поэтомуReactНовое в версии 16.3Context API, так что вStrictModeобнаружит, использует ли приложение устаревшиеContext API.

Поскольку старый API контекста будет привязан к провайдеру контекстаchildContextTypesа такжеgetChildContextи привязка к потребителю контекста для доступа к контекстуcontextTypesимущество, поэтомуStrictModeПосле завершения создания экземпляра компонента можно определить, используется ли старый Context API, оценив, имеет ли экземпляр эти атрибуты или нет, а затем выдать унифицированное предупреждение.

5. Предупреждение об использовании API ссылки на строку

Хотя эта часть содержания и упоминается в официальных документах, но после авторскогоэксперимент, и не может бытьStrictModeследующая пара используетсяstring ref APIПоведение вызывает предупреждение в консоли, поэтому я не буду упоминать его здесь.

напиши в конце

StrictModeдействительно помогает нам сделатьReactПрограммы работают лучше и надежнее, в этом нет никаких сомнений. Но я думаю, что вОбнаружение неожиданных побочных эффектовНа данный момент то, что делает React, недостаточно дружелюбно для разработчиков, хотя проще найти неожиданные побочные эффекты для некоторых методов, которые вызываются дважды, но для новичковReactлицо или правоStrictModeДля людей, которые не знают достаточно, они, скорее всего, думают, что этоReactЕсть проблема или проблема с собственным методом написания, что приводит к повторным вызовам и трате ненужного времени на отладку. В этом отношении может понадобиться более дружественный совет.