Component¶
Мы рекомендуем определять компоненты как функции, а не как классы.
Component
- это базовый класс для компонентов React, определенных как классы JavaScript. Классовые компоненты все еще поддерживаются React, но мы не рекомендуем использовать их в новом коде.
1 2 3 4 5 |
|
Описание¶
Component
¶
Чтобы определить компонент React как класс, расширьте встроенный класс Component
и определите метод render
:
1 2 3 4 5 6 7 |
|
Только метод render
является обязательным, остальные методы необязательны.
context
¶
Контекст компонента класса доступен как this.context
. Он доступен только если вы укажете какой контекст вы хотите получить, используя static contextType
(современный) или static contextTypes
(устаревший).
Компонент класса может одновременно считывать только один контекст.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Контекст
Чтение this.context
в компонентах класса эквивалентно useContext
в компонентах функции.
props
¶
Пропсы, передаваемые компоненту класса, доступны как this.props
.
1 2 3 4 5 6 7 |
|
Пропсы
Чтение this.props
в компонентах классов эквивалентно объявлению props в компонентах функций.
refs
¶
Устарело
Этот API будет удален в одной из будущих основных версий React. Вместо него используйте createRef
.
Позволяет получить доступ к legacy string refs для этого компонента.
state
¶
Состояние компонента класса доступно как this.state
. Поле state
должно быть объектом. Не изменяйте состояние напрямую. Если вы хотите изменить состояние, вызовите setState
с новым состоянием.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Состояние
Определение state
в компонентах класса эквивалентно вызову useState
в компонентах функции.
constructor(props)
¶
Конструктор constructor запускается перед тем, как компонент вашего класса монтируется (добавляется на экран). Как правило, конструктор используется в React только для двух целей. Он позволяет вам объявить состояние и привязать методы вашего класса к экземпляру класса:
1 2 3 4 5 6 7 8 9 10 11 |
|
Если вы используете современный синтаксис JavaScript, конструкторы нужны редко. Вместо этого вы можете переписать приведенный выше код, используя синтаксис public class field syntax, который поддерживается как современными браузерами, так и инструментами типа Babel:.
1 2 3 4 5 6 7 |
|
Конструктор не должен содержать никаких побочных эффектов или подписок.
Параметры
props
: Начальные параметры компонента.
Возвращает
constructor
не должен ничего возвращать.
Ограничения
-
Не запускайте в конструкторе никаких побочных эффектов или подписок. Вместо этого используйте
componentDidMount
. -
Внутри конструктора необходимо вызывать
super(props)
перед любым другим оператором. Если этого не сделать, тоthis.props
будетнеопределенным
во время работы конструктора, что может запутать и привести к ошибкам. -
Конструктор - это единственное место, где вы можете присвоить
this.state
напрямую. Во всех остальных методах вместо этого нужно использоватьthis.setState()
. Не вызывайтеsetState
в конструкторе. -
При использовании серверного рендеринга, конструктор будет выполняться и на сервере, а за ним последует метод
render
. Однако методы жизненного цикла, такие какcomponentDidMount
илиcomponentWillUnmount
, не будут выполняться на сервере. -
Когда включен Строгий режим, React будет вызывать
constructor
дважды в процессе разработки, а затем выбрасывать один из экземпляров. Это поможет вам заметить случайные побочные эффекты, которые необходимо вынести за пределыконструктора
.
Точного эквивалента constructor
в функциональных компонентах не существует. Чтобы объявить состояние в функциональном компоненте, вызовите useState
. Чтобы избежать пересчета начального состояния, передайте функцию useState
.
componentDidCatch(error, info)
¶
Если вы определите componentDidCatch
, React будет вызывать его, когда какой-либо дочерний компонент (включая удаленные дочерние компоненты) выкинет ошибку во время рендеринга. Это позволит вам регистрировать эту ошибку на службе сообщений об ошибках в продакшене.
Обычно этот метод используется вместе с static getDerivedStateFromError
, который позволяет обновить состояние в ответ на ошибку и вывести сообщение об ошибке пользователю. Компонент с этими методами называется граница ошибки.
Параметры
-
error
: Ошибка, которая была выдана. На практике это обычно будет экземплярError
, но это не гарантировано, поскольку JavaScript позволяетthrow
любое значение, включая строки или дажеnull
. -
info
: Объект, содержащий дополнительную информацию об ошибке. Его полеcomponentStack
содержит трассировку стека с компонентом, который бросил, а также имена и местоположение источников всех его родительских компонентов. В продакшене имена компонентов будут минифицированы. Если вы настроите prod
Возврат
componentDidCatch
не должен ничего возвращать.
Ограничения
-
В прошлом было принято вызывать
setState
внутриcomponentDidCatch
, чтобы обновить пользовательский интерфейс и отобразить сообщение об ошибке. Это устарело в пользу определенияstatic getDerivedStateFromError
. -
Производственные и девелоперские сборки React немного отличаются в том, как
componentDidCatch
обрабатывает ошибки. В разработке ошибки будут всплывать вwindow
, что означает, что любыеwindow.onerror
илиwindow.addEventListener('error', callback)
будут перехватывать ошибки, которые были пойманыcomponentDidCatch
. В производстве, вместо этого, ошибки не будут всплывать, что означает, что любой обработчик ошибок предка будет получать только ошибки, явно не пойманныеcomponentDidCatch
.
Прямого эквивалента для componentDidCatch
в компонентах функций пока не существует. Если вы хотите избежать создания компонентов классов, напишите один компонент ErrorBoundary
, как описано выше, и используйте его во всем приложении. В качестве альтернативы вы можете использовать пакет react-error-boundary
, который сделает это за вас.
componentDidMount()
¶
Если вы определите метод componentDidMount
, React будет вызывать его, когда ваш компонент будет добавлен (смонтирован) на экран. Это обычное место для начала получения данных, установки подписок или манипулирования узлами DOM.
Если вы реализуете componentDidMount
, вам обычно необходимо реализовать другие методы жизненного цикла, чтобы избежать ошибок. Например, если componentDidMount
считывает некоторые состояния или пропсы, вам также необходимо реализовать componentDidUpdate
для обработки их изменений и componentWillUnmount
для очистки того, что делал componentDidMount
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Параметры
componentDidMount
не принимает никаких параметров.
Возвращает
componentDidMount
не должен ничего возвращать.
Ограничения
-
Когда включен Строгий режим, при разработке React будет вызывать
componentDidMount
, затем сразу же вызыватьcomponentWillUnmount
, и затем снова вызыватьcomponentDidMount
. Это поможет вам заметить, если вы забыли реализоватьcomponentWillUnmount
или если его логика не полностью "отражает" то, что делаетcomponentDidMount
. -
Хотя вы можете вызвать
setState
непосредственно вcomponentDidMount
, лучше избегать этого, когда это возможно. Это вызовет дополнительный рендеринг, но он произойдет до того, как браузер обновит экран. Это гарантирует, что даже еслиrender
будет вызван дважды в этом случае, пользователь не увидит промежуточного состояния. Используйте этот паттерн с осторожностью, поскольку он часто вызывает проблемы с производительностью. В большинстве случаев вы можете назначить начальное состояние вconstructor
. Тем не менее, это может быть необходимо в таких случаях, как модалы и всплывающие подсказки, когда вам нужно измерить узел DOM перед отрисовкой чего-то, что зависит от его размера или положения.
Монтирование компонента
Для многих случаев использования определение componentDidMount
, componentDidUpdate
и componentWillUnmount
вместе в компонентах класса эквивалентно вызову useEffect
в компонентах функций. В редких случаях, когда важно, чтобы код выполнялся перед отрисовской браузера, более подходящим вариантом является useLayoutEffect
.
componentDidUpdate(prevProps, prevState, snapshot?)
¶
Если вы определите метод componentDidUpdate
, React вызовет его сразу после того, как ваш компонент будет перерендерирован с обновленными пропсами или состоянием. Этот метод не вызывается для первоначального рендеринга.
Вы можете использовать его для манипуляций с DOM после обновления. Это также обычное место для выполнения сетевых запросов, если вы сравниваете текущие пропсы с предыдущими (например, сетевой запрос может не потребоваться, если пропсе изменились). Обычно вы используете его вместе с componentDidMount
и componentWillUnmount
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Параметры
prevProps
: пропсы до обновления. СравнитеprevProps
сthis.props
, чтобы определить, что изменилось.prevState
: Состояние перед обновлением. СравнитеprevState
сthis.state
, чтобы определить, что изменилось.snapshot
: Если вы реализовалиgetSnapshotBeforeUpdate
,snapshot
будет содержать значение, которое вы вернули из этого метода. В противном случае оно будетundefined
.
Возвращает
componentDidUpdate
не должен ничего возвращать.
Предупреждения
-
componentDidUpdate
не будет вызван, еслиshouldComponentUpdate
определен и возвращаетfalse
. -
Логика внутри
componentDidUpdate
обычно должна быть обернута в условия, сравнивающиеthis.props
сprevProps
, аthis.state
сprevState
. В противном случае есть риск создания бесконечных циклов. -
Хотя вы можете вызвать
setState
непосредственно вcomponentDidUpdate
, лучше избегать этого, когда это возможно. Это вызовет дополнительный рендеринг, но он произойдет до того, как браузер обновит экран. Это гарантирует, что хотяrender
в этом случае будет вызван дважды, пользователь не увидит промежуточного состояния. Этот паттерн часто вызывает проблемы с производительностью, но он может быть необходим в редких случаях, таких как модалы и всплывающие подсказки, когда вам нужно измерить узел DOM перед рендерингом чего-то, что зависит от его размера или положения.
Для многих случаев использования определение componentDidMount
, componentDidUpdate
и componentWillUnmount
вместе в компонентах класса эквивалентно вызову useEffect
в компонентах функций. В редких случаях, когда важно, чтобы код выполнялся перед закраской браузера, более подходящим вариантом является useLayoutEffect
.
componentWillMount()
¶
Устарело
Этот API был переименован из componentWillMount
в UNSAFE_componentWillMount
Старое название было устаревшим. В будущей основной версии React будет работать только новое название.
Запустите rename-unsafe-lifecycles
codemod для автоматического обновления ваших компонентов.
componentWillReceiveProps(nextProps)
¶
Устарело
Этот API был переименован из componentWillReceiveProps
в UNSAFE_componentWillReceiveProps
Старое название было устаревшим. В будущей основной версии React будет работать только новое название.
Запустите кодмод rename-unsafe-lifecycles
для автоматического обновления.
componentWillUpdate(nextProps, nextState)
¶
Устарело
Этот API был переименован из componentWillUpdate
в UNSAFE_componentWillUpdate
Старое название было устаревшим. В будущей основной версии React будет работать только новое название.
Запустите rename-unsafe-lifecycles
codemod для автоматического обновления ваших компонентов.
componentWillUnmount()
¶
Если вы определите метод componentWillUnmount
, React вызовет его перед тем, как ваш компонент будет удален (размонтирован) с экрана. Это обычное место для отмены получения данных или удаления подписок.
Логика внутри componentWillUnmount
должна "отражать" логику внутри componentDidMount
. Например, если componentDidMount
устанавливает подписку, componentWillUnmount
должен очистить эту подписку. Если логика очистки в вашем componentWillUnmount
считывает некоторые пропсы или состояние, вам обычно также потребуется реализовать componentDidUpdate
для очистки ресурсов (таких как подписки), соответствующих старым пропсам и состоянию.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Параметры
componentWillUnmount
не принимает никаких параметров.
Возвращает
componentWillUnmount
не должен ничего возвращать.
Ограничения
- Когда включен Строгий режим, при разработке React будет вызывать
componentDidMount
, затем сразу же вызыватьcomponentWillUnmount
, а затем снова вызыватьcomponentDidMount
. Это поможет вам заметить, если вы забыли реализоватьcomponentWillUnmount
или если его логика не полностью "отражает" то, что делаетcomponentDidMount
.
Для многих случаев использования определение componentDidMount
, componentDidUpdate
и componentWillUnmount
вместе в компонентах класса эквивалентно вызову useEffect
в компонентах функций. В редких случаях, когда важно, чтобы код выполнялся перед закраской браузера, более подходящим вариантом является useLayoutEffect
.
forceUpdate(callback?)
¶
Принуждает компонент к повторному рендерингу.
Обычно в этом нет необходимости. Если метод render
вашего компонента читает только из this.props
, this.state
или this.context
, то он будет перерендерирован автоматически, когда вы вызовете setState
внутри вашего компонента или одного из его родителей. Однако если метод render
вашего компонента считывает данные непосредственно из внешнего источника данных, вам необходимо указать React обновлять пользовательский интерфейс при изменении источника данных. Именно это и позволяет сделать forceUpdate
.
Старайтесь избегать всех случаев использования forceUpdate
и читайте только из this.props
и this.state
в render
.
Параметры
- опционально
callback
Если указано, React вызовет указанный вамиcallback
после фиксации обновления.
Возвращаемое значение
forceUpdate
ничего не возвращает.
Предостережения
- Если вы вызовете
forceUpdate
, React выполнит повторный рендеринг без вызоваshouldComponentUpdate
.
Чтение внешнего источника данных и принуждение компонентов класса к повторному рендерингу в ответ на его изменения с помощью forceUpdate
было заменено на useSyncExternalStore
в компонентах функций.
getChildContext()
¶
Устарело
Этот API будет удален в одной из будущих основных версий React. Вместо него используйте Context.Provider
.
Позволяет указать значения для унаследованного контекста, предоставляемого этим компонентом.
getSnapshotBeforeUpdate(prevProps, prevState)
¶
Если вы реализуете getSnapshotBeforeUpdate
, React будет вызывать его непосредственно перед тем, как React обновит DOM. Это позволит вашему компоненту захватить некоторую информацию из DOM (например, позицию прокрутки) до того, как она будет потенциально изменена. Любое значение, возвращаемое этим методом жизненного цикла, будет передано в качестве параметра в componentDidUpdate
.
Например, вы можете использовать его в пользовательском интерфейсе, таком как поток чата, который должен сохранять позицию прокрутки во время обновления:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
В приведенном выше примере важно прочитать свойство scrollHeight
непосредственно в getSnapshotBeforeUpdate
. Небезопасно читать его в render
, UNSAFE_componentWillReceiveProps
или UNSAFE_componentWillUpdate
, поскольку существует потенциальный разрыв во времени между вызовом этих методов и обновлением DOM в React.
Параметры
-
prevProps
: пропсы до обновления. СравнитеprevProps
сthis.props
, чтобы определить, что изменилось. -
prevState
: Состояние перед обновлением. СравнитеprevState
сthis.state
, чтобы определить, что изменилось.
Возвращаемое значение
Вы должны вернуть значение снапшота любого типа, который вы хотите, или null
. Возвращенное значение будет передано в качестве третьего аргумента в componentDidUpdate
.
Ограничения
getSnapshotBeforeUpdate
не будет вызван, если определеноshouldComponentUpdate
и возвращаетfalse
.
На данный момент не существует эквивалента getSnapshotBeforeUpdate
для компонентов функций. Это очень редкий случай использования, но если у вас возникнет такая необходимость, то пока вам придется написать компонент класса.
render()
¶
Метод render
является единственным обязательным методом в компоненте класса.
Метод render
должен определять, что вы хотите видеть на экране, например:
1 2 3 4 5 6 7 |
|
React может вызвать render
в любой момент, поэтому не стоит предполагать, что он выполняется в определенное время. Обычно метод render
должен возвращать часть JSX, но поддерживаются и некоторые другие типы возврата (например, строки). Для вычисления возвращаемого JSX метод render
может читать this.props
, this.state
и this.context
.
Вы должны написать метод render
как чистую функцию, что означает, что он должен возвращать один и тот же результат, если пропсы, состояние и контекст одинаковы. Он также не должен содержать побочных эффектов (таких как установка подписок) или взаимодействовать с API браузера. Побочные эффекты должны происходить либо в обработчиках событий, либо в методах типа componentDidMount
.
Параметры
-
prevProps
: пропсы до обновления. СравнитеprevProps
сthis.props
, чтобы определить, что изменилось. -
prevState
: Состояние перед обновлением. СравнитеprevState
сthis.state
, чтобы определить, что изменилось.
Возвращаемое значение
render
может возвращать любой допустимый узел React. Сюда входят такие элементы React, как <div />
, строки, числа, порталы, пустые узлы (null
, undefined
, true
и false
) и массивы узлов React.
Ограничения
-
render
должна быть написана как чистая функция props, state и context. Она не должна иметь побочных эффектов. -
render
не будет вызван, если определеноshouldComponentUpdate
и возвращаетfalse
. -
Когда включен Strict Mode, React будет вызывать
render
дважды в процессе разработки, а затем отбрасывать один из результатов. Это поможет вам заметить случайные побочные эффекты, которые необходимо убрать из методаrender
. -
Между вызовом
render
и последующим вызовомcomponentDidMount
илиcomponentDidUpdate
нет соответствия один к одному. Некоторые результаты вызоваrender
могут быть отброшены React, когда это будет полезно.
setState(nextState, callback?)
¶
Вызовите setState
для обновления состояния вашего компонента React.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
setState
регистрирует изменения в состоянии компонента. Он сообщает React, что этот компонент и его дочерние элементы должны быть перерисованы с новым состоянием. Это основной способ обновления пользовательского интерфейса в ответ на взаимодействие.
Вызов setState
не изменяет текущее состояние в уже выполняющемся коде:
1 2 3 4 5 6 7 |
|
Это влияет только на то, что this.state
будет возвращать, начиная со следующего рендера.
Вы также можете передать функцию в setState
. Это позволит вам обновить состояние на основе предыдущего состояния:
1 2 3 4 5 6 7 |
|
Это не обязательно, но удобно, если вы хотите обновить состояние несколько раз во время одного и того же события.
Параметры
nextState
: Либо объект, либо функция.- Если вы передадите объект в качестве
nextState
, он будет неглубоко объединен сthis.state
. - Если вы передадите функцию в качестве
nextState
, она будет рассматриваться как функция обновления. Она должна быть чистой, принимать в качестве аргументов состояние ожидания и пропс, и возвращать объект, который будет неглубоко объединен вthis.state
. React поместит вашу функцию обновления в очередь и перерендерит ваш компонент. Во время следующего рендеринга React вычислит следующее состояние, применив все стоящие в очереди функции обновления к предыдущему состоянию.
- Если вы передадите объект в качестве
- опциональный
callback
: Если указано, React вызовет указанный вамиcallback
после фиксации обновления.
Возвращаемое значение
setState
ничего не возвращает.
Предостережения
-
Рассматривайте
setState
как запрос, а не как немедленную команду на обновление компонента. Когда несколько компонентов обновляют свое состояние в ответ на событие, React будет собирать их обновления и перерисовывать их вместе за один проход в конце события. В редких случаях, когда вам нужно заставить определенное обновление состояния применяться синхронно, вы можете обернуть его вflushSync
, но это может снизить производительность. -
setState
не обновляетthis.state
немедленно. Это делает чтениеthis.state
сразу после вызоваsetState
потенциально опасным. Вместо этого используйтеcomponentDidUpdate
или аргумент setStatecallback
, любой из которых гарантированно сработает после применения обновления. Если вам нужно установить состояние на основе предыдущего состояния, вы можете передать функцию вnextState
, как описано выше.
Вызов setState
в компонентах классов аналогичен вызову функции set
в компонентах функций.
shouldComponentUpdate(nextProps, nextState, nextContext)
¶
Если вы определите shouldComponentUpdate
, React будет вызывать его, чтобы определить, можно ли пропустить повторный рендеринг.
Если вы уверены, что хотите написать его вручную, вы можете сравнить this.props
с nextProps
и this.state
с nextState
и вернуть false
, чтобы сообщить React, что обновление можно пропустить.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
React вызывает shouldComponentUpdate
перед рендерингом при получении новых пропсов или состояния. По умолчанию установлено значение true
. Этот метод не вызывается для начального рендеринга или при использовании forceUpdate
.
Параметры
nextProps
: Следующий пропс, с которым компонент будет рендериться. СравнитеnextProps
сthis.props
, чтобы определить, что изменилось.nextState
: Следующее состояние, в котором компонент будет отображаться. СравнитеnextState
сthis.state
, чтобы определить, что изменилось.nextContext
: Следующий контекст, с которым компонент собирается выполнить рендеринг. СравнитеnextContext
сthis.context
, чтобы определить, что изменилось. Доступно только если вы указалиstatic contextType
(современный) илиstatic contextTypes
(унаследованный).
Возвращает
Возвращает true
, если вы хотите, чтобы компонент был перерендерен. Это поведение по умолчанию.
Верните false
, чтобы сообщить React, что повторный рендеринг можно пропустить.
Ограничения
-
Этот метод только существует как оптимизация производительности. Если ваш компонент ломается без него, сначала исправьте это.
-
Рассмотрите возможность использования
PureComponent
вместо написанияshouldComponentUpdate
вручную.PureComponent
неглубоко сравнивает пропсы и состояние и уменьшает вероятность того, что вы пропустите необходимое обновление. -
Мы не рекомендуем выполнять глубокие проверки равенства или использовать
JSON.stringify
вshouldComponentUpdate
. Это делает производительность непредсказуемой и зависимой от структуры данных каждого пропса и состояния. В лучшем случае вы рискуете внести многосекундные задержки в ваше приложение, а в худшем - завалить его. -
Возврат
false
не предотвращает повторный рендеринг дочерних компонентов при изменении их состояния. -
Возврат
false
не гарантирует, что компонент не будет повторно отображаться. React будет использовать возвращаемое значение как подсказку, но он все равно может решить перерисовать ваш компонент, если это имеет смысл сделать по другим причинам.
Оптимизация компонентов классов с помощью shouldComponentUpdate
аналогична оптимизации компонентов функций с помощью memo
. Компоненты функций также предлагают более детальную оптимизацию с помощью useMemo
.
UNSAFE_componentWillMount()
¶
Если вы определите UNSAFE_componentWillMount
, React вызовет его сразу после constructor
. Он существует только по историческим причинам и не должен использоваться в любом новом коде. Вместо этого используйте одну из альтернатив:
- Для инициализации состояния объявите
state
как поле класса или установитеthis.state
внутриconstructor
. - Если вам нужно запустить побочный эффект или установить подписку, перенесите эту логику в
componentDidMount
.
Параметры
UNSAFE_componentWillMount
не принимает никаких параметров.
Возвращает
UNSAFE_componentWillMount
не должен ничего возвращать.
Ограничения
-
UNSAFE_componentWillMount
не будет вызван, если компонент реализуетstatic getDerivedStateFromProps
илиgetSnapshotBeforeUpdate
. -
Несмотря на свое название,
UNSAFE_componentWillMount
не гарантирует, что компонент будет смонтирован, если ваше приложение использует современные функции React, такие какSuspense
. Если попытка рендеринга приостановлена (например, потому что код для какого-то дочернего компонента еще не загружен), React отбросит дерево процесса и попытается построить компонент с нуля во время следующей попытки. Вот почему этот метод является "небезопасным". Код, который полагается на монтирование (например, добавление подписки), должен идти вcomponentDidMount
. -
UNSAFE_componentWillMount
- это единственный метод жизненного цикла, который выполняется во время рендеринга сервера. Для всех практических целей он идентиченconstructor
, поэтому для такого типа логики следует использоватьconstructor
.
Вызов setState
внутри UNSAFE_componentWillMount
в компоненте класса для инициализации состояния эквивалентен передаче этого состояния в качестве начального состояния в useState
в компоненте функции.
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
¶
Если вы определите UNSAFE_componentWillReceiveProps
, React будет вызывать его, когда компонент получит новые пропсы. Оно существует только по историческим причинам и не должно использоваться в новом коде. Вместо этого используйте одну из альтернатив:
- Если вам нужно запустить побочный эффект (например, получить данные, запустить анимацию или переинициализировать подписку) в ответ на изменение пропса, перенесите эту логику в
componentDidUpdate
. - Если вам нужно избежать повторного вычисления некоторых данных только при изменении пропса, используйте вместо этого memoization helper.
- Если вам нужно "сбросить" некоторое состояние при изменении пропса, рассмотрите возможность сделать компонент полностью управляемым или полностью неуправляемым с ключом.
- Если вам нужно "подправить" некоторое состояние при изменении пропса, проверьте, можете ли вы вычислить всю необходимую информацию только из пропсов во время рендеринга. Если нет, используйте вместо этого статический
getDerivedStateFromProps
.
См. примеры перехода от небезопасных жизненных циклов.
Параметры
nextProps
: Следующий пропс, который компонент собирается получить от своего родительского компонента. СравнитеnextProps
сthis.props
, чтобы определить, что изменилось.nextContext
: Следующий пропс, который компонент собирается получить от ближайшего провайдера. СравнитеnextContext
сthis.context
, чтобы определить, что изменилось. Доступно только если вы указалиstatic contextType
(современный) илиstatic contextTypes
(унаследованный).
Возвращает
UNSAFE_componentWillReceiveProps
не должен ничего возвращать.
Ограничения
-
UNSAFE_componentWillReceiveProps
не будет вызван, если компонент реализуетstatic getDerivedStateFromProps
илиgetSnapshotBeforeUpdate
. -
Несмотря на свое название,
UNSAFE_componentWillReceiveProps
не гарантирует, что компонент получит эти props, если ваше приложение использует современные функции React, такие какSuspense
. Если попытка рендеринга приостановлена (например, потому что код для какого-то дочернего компонента еще не загружен), React отбросит текущее дерево и попытается построить компонент с нуля во время следующей попытки. К моменту следующей попытки рендеринга пропс может быть другим. Вот почему этот метод является "небезопасным". Код, который должен выполняться только для зафиксированных обновлений (например, сброс подписки), следует поместить вcomponentDidUpdate
. -
UNSAFE_componentWillReceiveProps
не означает, что компонент получил другие пропсы, чем в прошлый раз. Вам нужно самостоятельно сравнитьnextProps
иthis.props
, чтобы проверить, изменилось ли что-то. -
React не вызывает
UNSAFE_componentWillReceiveProps
с начальными пропсами во время монтирования. Он вызывает этот метод только в том случае, если некоторые пропсы компонента будут обновлены. Например, вызовsetState
обычно не вызываетUNSAFE_componentWillReceiveProps
внутри того же компонента.
Вызов setState
внутри UNSAFE_componentWillReceiveProps
в компоненте класса для "корректировки" состояния эквивалентен вызову функции set
из useState
во время рендеринга в компоненте функции.
UNSAFE_componentWillUpdate(nextProps, nextState)
¶
Если вы определите UNSAFE_componentWillUpdate
, React будет вызывать его перед рендерингом с новыми props или state. Он существует только по историческим причинам и не должен использоваться в новом коде. Вместо этого используйте одну из альтернатив:
-
Если вам нужно запустить побочный эффект (например, получить данные, запустить анимацию или повторно инициализировать подписку) в ответ на изменение пропса или состояния, перенесите эту логику в
componentDidUpdate
. -
Если вам нужно прочитать какую-то информацию из DOM (например, сохранить текущую позицию прокрутки), чтобы позже использовать ее в
componentDidUpdate
, прочитайте ее внутриgetSnapshotBeforeUpdate
.
См. примеры перехода от небезопасных жизненных циклов.
Параметры
nextProps
: Следующий пропс, с которым компонент собирается выполнить рендеринг. СравнитеnextProps
сthis.props
, чтобы определить, что изменилось.nextState
: Следующее состояние, в котором компонент будет отображаться. СравнитеnextState
сthis.state
, чтобы определить, что изменилось.
Возвращает
UNSAFE_componentWillUpdate
не должен ничего возвращать.
Предостережения
-
UNSAFE_componentWillUpdate
не будет вызван, еслиshouldComponentUpdate
определен и возвращаетfalse
. -
UNSAFE_componentWillUpdate
не будет вызван, если компонент реализуетstatic getDerivedStateFromProps
илиgetSnapshotBeforeUpdate
. -
Не поддерживается вызов
setState
(или любого метода, который приводит к вызовуsetState
, например, диспетчеризация действия Redux) во времяcomponentWillUpdate
. -
Несмотря на свое название,
UNSAFE_componentWillUpdate
не гарантирует, что компонент обновится, если ваше приложение использует современные функции React, такие какSuspense
. Если попытка рендеринга приостановлена (например, потому что код для какого-то дочернего компонента еще не загружен), React отбросит дерево процесса и попытается построить компонент с нуля во время следующей попытки. К моменту следующей попытки рендеринга пропсы и состояние могут быть другими. Вот почему этот метод является "небезопасным". Код, который должен выполняться только для зафиксированных обновлений (например, сброс подписки), следует поместить вcomponentDidUpdate
. -
UNSAFE_componentWillUpdate
не означает, что компонент получил другой пропс или состояние, чем в прошлый раз. Вам нужно самостоятельно сравнитьnextProps
сthis.props
иnextState
сthis.state
, чтобы проверить, изменилось ли что-то. -
React не вызывает
UNSAFE_componentWillUpdate
с начальными props и state во время монтирования.
Не существует прямого эквивалента UNSAFE_componentWillUpdate
в функциональных компонентах.
static childContextTypes
¶
Устарело
Этот API будет удален в одной из будущих основных версий React. Вместо него используйте статический contextType
.
Позволяет указать, какой legacy context предоставляется этим компонентом.
static contextTypes
¶
Устарело
Этот API будет удален в одной из будущих основных версий React. Вместо него используйте статический contextType
.
Позволяет указать, какой legacy context потребляется этим компонентом.
static contextType
¶
Если вы хотите читать this.context
из компонента вашего класса, вы должны указать, какой контекст он должен читать. Контекст, который вы указываете в качестве static contextType
, должен быть значением, ранее созданным с помощью createContext
.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Чтение this.context
в компонентах класса эквивалентно useContext
в компонентах функции.
static defaultProps
¶
Вы можете определить static defaultProps
, чтобы установить пропсы по умолчанию для класса. Они будут использоваться для неопределенных
и отсутствующих пропсов, но не для пропсов null
.
Например, вот как определить, что пропс color
должен по умолчанию иметь значение 'blue'
:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Если параметр color
не указан или является неопределенным
, он будет установлен по умолчанию в синий
:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Определение defaultProps
в компонентах классов аналогично использованию значений по умолчанию в компонентах функций.
static propTypes
¶
Вы можете определить static propTypes
вместе с библиотекой prop-types
, чтобы объявить типы пропсов, принимаемых вашим компонентом. Эти типы будут проверяться во время рендеринга и только в процессе разработки.
1 2 3 4 5 6 7 8 9 10 11 |
|
Мы рекомендуем использовать TypeScript вместо проверки типов пропсов во время выполнения.
static getDerivedStateFromError(error)
¶
Если вы определите static getDerivedStateFromError
, React будет вызывать его, когда дочерний компонент (включая удаленные дочерние компоненты) бросит ошибку во время рендеринга. Это позволит вам отобразить сообщение об ошибке вместо того, чтобы очищать пользовательский интерфейс.
Обычно этот метод используется вместе с componentDidCatch
, который позволяет отправить отчет об ошибке в какой-либо аналитический сервис. Компонент с этими методами называется граница ошибки.
Параметры
error
: Ошибка, которая была выдана. На практике это обычно будет экземплярError
, но это не гарантировано, поскольку JavaScript позволяетthrow
любое значение, включая строки или дажеnull
.
Возвращает
static getDerivedStateFromError
должен возвращать состояние, указывающее компоненту на отображение сообщения об ошибке.
Ограничения
- Функция
static getDerivedStateFromError
должна быть чистой функцией. Если вы хотите выполнить побочный эффект (например, вызвать аналитический сервис), вам необходимо также реализоватьcomponentDidCatch
.
Прямого эквивалента для static getDerivedStateFromError
в компонентах функций пока не существует. Если вы хотите избежать создания компонентов классов, напишите один компонент ErrorBoundary
, как описано выше, и используйте его во всем приложении. В качестве альтернативы используйте пакет react-error-boundary
, который делает это.
static getDerivedStateFromProps(props, state)
¶
Если вы определите static getDerivedStateFromProps
, React будет вызывать его непосредственно перед вызовом render
, как при первоначальном монтаже, так и при последующих обновлениях. Он должен вернуть объект для обновления состояния, или null
, чтобы ничего не обновлять.
Этот метод существует для редких случаев использования, когда состояние зависит от изменений в пропсах с течением времени. Например, этот компонент Form
сбрасывает состояние email
при изменении пропса userID
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Обратите внимание, что этот паттерн требует, чтобы вы хранили предыдущее значение пропса (например, userID
) в состоянии (например, prevUserID
).
Выведение состояния приводит к многословному коду и делает ваши компоненты сложными для осмысления. Убедитесь, что вы знакомы с более простыми альтернативами:
- Если вам нужно выполнить побочный эффект (например, выборку данных или анимацию) в ответ на изменение пропса, используйте метод
componentDidUpdate
. - Если вы хотите пересчитывать некоторые данные только при изменении пропса, используйте вместо этого помощник мемоизации.
- Если вы хотите "сбросить" некоторое состояние при изменении пропса, рассмотрите возможность сделать компонент полностью управляемым или полностью неуправляемым с ключом.
Параметры
props
: Следующий пропс, с которым компонент собирается выполнить рендеринг.state
: Следующее состояние, с которым компонент будет рендериться.
Возвращает
static getDerivedStateFromProps
возвращает объект для обновления состояния, или null
для отсутствия обновления.
Ограничения
-
Этот метод срабатывает при каждом рендере, независимо от причины. Это отличается от
UNSAFE_componentWillReceiveProps
, который срабатывает только тогда, когда родитель вызывает повторный рендеринг, а не в результате локальногоsetState
. -
Этот метод не имеет доступа к экземпляру компонента. Если вы хотите, вы можете повторно использовать некоторый код между
static getDerivedStateFromProps
и другими методами класса, извлекая чистые функции пропсов и состояния компонента за пределы определения класса.
Реализация static getDerivedStateFromProps
в компоненте класса эквивалентна вызову функции set
из useState
во время рендеринга в компоненте функции.
Использование¶
Определение компонента класса¶
Чтобы определить компонент React как класс, расширьте встроенный класс Component
и определите метод render
:
1 2 3 4 5 6 7 |
|
React будет вызывать ваш метод render
всякий раз, когда ему нужно будет определить, что отобразить на экране. Обычно вы будете возвращать из него некий JSX. Ваш метод render
должен быть чистой функцией: он должен только вычислять JSX.
Аналогично функциональным компонентам, компонент класса может получать информацию по props от своего родительского компонента. Однако синтаксис для чтения пропсов отличается. Например, если родительский компонент отображает <Greeting name="Taylor" />
, то вы можете прочитать пропс name
из this.props
, как this.props.name
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Обратите внимание, что хуки (функции, начинающиеся с use
, например useState
) не поддерживаются внутри компонентов классов.
Мы рекомендуем определять компоненты как функции, а не как классы.
Добавление состояния в компонент класса¶
Чтобы добавить state в класс, присвойте объект свойству state
. Чтобы обновить состояние, вызовите this.setState
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Добавление методов жизненного цикла в компонент класса¶
Есть несколько специальных методов, которые вы можете определить для своего класса.
Если вы определите метод componentDidMount
, React будет вызывать его, когда ваш компонент будет добавлен (смонтирован) на экран. React вызовет метод componentDidUpdate
после того, как ваш компонент изменит рендеринг из-за изменения пропсов или состояния. React вызовет componentWillUnmount
после того, как ваш компонент будет удален (размонтирован) с экрана.
Если вы реализуете componentDidMount
, вам обычно нужно реализовать все три жизненных цикла, чтобы избежать ошибок. Например, если componentDidMount
считывает некоторые состояния или пропсы, вы также должны реализовать componentDidUpdate
для обработки их изменений, и componentWillUnmount
для очистки всего, что делал componentDidMount
.
Например, этот компонент ChatRoom
поддерживает соединение чата, синхронизированное с пропсами и состоянием:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Обратите внимание, что при разработке, когда включен Strict Mode, React вызовет componentDidMount
, тут же вызовет componentWillUnmount
, а затем снова вызовет componentDidMount
. Это поможет вам заметить, если вы забыли реализовать componentWillUnmount
или если его логика не полностью "зеркальна" тому, что делает componentDidMount
.
Ловля ошибок рендеринга с границей ошибки¶
По умолчанию, если ваше приложение выдаст ошибку во время рендеринга, React удалит свой UI с экрана. Чтобы предотвратить это, вы можете обернуть часть вашего пользовательского интерфейса в границу ошибки. Граница ошибки - это специальный компонент, который позволяет отображать некоторый резервный пользовательский интерфейс вместо той части, которая потерпела крах - например, сообщение об ошибке.
Чтобы реализовать компонент границы ошибки, вам нужно предоставить static getDerivedStateFromError
, который позволяет обновлять состояние в ответ на ошибку и выводить пользователю сообщение об ошибке. Вы также можете реализовать componentDidCatch
для добавления дополнительной логики, например, для регистрации ошибки в аналитическом сервисе.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Затем вы можете обернуть им часть дерева компонентов:
1 2 3 |
|
Если Profile
или его дочерний компонент выбросит ошибку, ErrorBoundary
"поймает" эту ошибку, отобразит резервный пользовательский интерфейс с сообщением об ошибке, которое вы предоставили, и отправит производственный отчет об ошибке в вашу службу сообщений об ошибках.
Вам не нужно оборачивать каждый компонент в отдельную границу ошибки. Когда вы думаете о гранулярности границ ошибок, подумайте, где имеет смысл отображать сообщение об ошибке. Например, в приложении для обмена сообщениями имеет смысл поместить границу ошибки вокруг списка бесед. Также имеет смысл поместить ее вокруг каждого отдельного сообщения. Однако не имеет смысла размещать границу вокруг каждого аватара.
В настоящее время не существует способа написать границу ошибки как компонент функции. Однако вам не обязательно писать класс границы ошибки самостоятельно. Например, вы можете использовать react-error-boundary
.
Альтернативы¶
Перенос простого компонента из класса в функцию¶
Обычно вместо этого вы определяете компоненты как функции.
Например, предположим, что вы преобразовываете компонент класса Greeting
в функцию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Определите функцию под названием Greeting
. Именно сюда вы переместите тело вашей функции render
.
1 2 3 |
|
Вместо this.props.name
определите пропс name
используя синтаксис деструктуризации и читайте его напрямую:
1 2 3 |
|
Вот полный пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Перенос компонента с состоянием из класса в функцию¶
Предположим, вы преобразовываете компонент класса Counter
в функцию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Начните с объявления функции с необходимыми переменными состояния:
1 2 3 4 5 6 7 |
|
Затем преобразуйте обработчики событий:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Наконец, замените все ссылки, начинающиеся с this
, на переменные и функции, которые вы определили в своем компоненте. Например, замените this.state.age
на age
, а this.handleNameChange
на handleNameChange
.
Вот полностью преобразованный компонент:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Перенос компонента с методами жизненного цикла из класса в функцию¶
Предположим, вы преобразовываете компонент класса ChatRoom
с методами жизненного цикла в функцию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Сначала убедитесь, что ваш componentWillUnmount
делает противоположное componentDidMount
. В приведенном выше примере это так: он разрывает соединение, которое устанавливает componentDidMount
. Если такая логика отсутствует, сначала добавьте ее.
Далее проверьте, что ваш метод componentDidUpdate
обрабатывает изменения всех пропсов и состояний, которые вы используете в componentDidMount
. В приведенном выше примере componentDidMount
вызывает setupConnection
, который считывает this.state.serverUrl
и this.props.roomId
. Именно поэтому componentDidUpdate
проверяет, изменились ли this.state.serverUrl
и this.props.roomId
, и сбрасывает соединение, если изменились. Если логика вашего componentDidUpdate
отсутствует или не обрабатывает изменения всех соответствующих пропсов и состояния, сначала исправьте это.
В приведенном выше примере логика внутри методов жизненного цикла соединяет компонент с системой вне React (сервером чата). Чтобы подключить компонент к внешней системе, опишите эту логику как один Эффект:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Этот вызов useEffect
эквивалентен логике в методах жизненного цикла, описанных выше. Если ваши методы жизненного цикла делают несколько несвязанных вещей, разделите их на несколько независимых Эффектов. Вот полный пример, с которым вы можете поиграть:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Если ваш компонент не синхронизируется с внешними системами, возможно, вам не нужен Эффект.
Перенос компонента с контекстом из класса в функцию¶
В этом примере компоненты классов Panel
и Button
считывают context из this.context
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
Когда вы преобразуете их в компоненты функций, замените вызовы this.context
на useContext
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
Источник — https://react.dev/reference/react/Component