Вы не можете использовать любого из существующих методов жизненного цикла ( componentDidMount
, componentDidUpdate
, и componentWillUnmount
т.д.) в крюке. Они могут использоваться только в компонентах класса. А с крючками вы можете использовать только функциональные компоненты. Строка ниже взята из документа React:
Если вы знакомы с React методы жизненного цикла класса, вы можете думать о useEffect
крючке componentDidMount
, componentDidUpdate
и в componentWillUnmount
сочетании.
Предположим, вы можете имитировать эти методы жизненного цикла из компонента класса в функциональные компоненты.
Код внутри componentDidMount
запускается один раз, когда компонент монтируется. useEffect
крюк-эквивалент для этого поведения
useEffect(() => {
// Your code here
}, []);
Обратите внимание на второй параметр здесь (пустой массив). Это будет работать только один раз.
Без второго параметраuseEffect
крючок будет вызываться каждый рендер компонент , который может быть опасным.
useEffect(() => {
// Your code here
});
componentWillUnmount
используется для очистки (например, удаление слушателей событий, отмена таймера и т. д.). Допустим, вы добавляете прослушиватель событий componentDidMount
и удаляете его, componentWillUnmount
как показано ниже.
componentDidMount() {
window.addEventListener('mousemove', () => {})
}
componentWillUnmount() {
window.removeEventListener('mousemove', () => {})
}
Хук-эквивалент вышеприведенного кода будет следующим
useEffect(() => {
window.addEventListener('mousemove', () => {});
// returned function will be called on component unmount
return () => {
window.removeEventListener('mousemove', () => {})
}
}, [])
useEffect()
функцию, спасибо.componentWillMount
componentWillMount
, нетcomponentWillUnmount
. Этот ответ действительно не отвечает на вопрос вообще, а просто повторяет то, что ОП уже подразумевало знать.хук useComponentDidMount
В большинстве случаев
useComponentDidMount
это инструмент для использования. Он будет запущен только один раз после монтирования компонента (начальная визуализация).useComponentWillMount
Важно отметить, что в классе компонентов
componentWillMount
считается наследство. Если вам нужен код для запуска только один раз до монтирования компонента, вы можете использовать конструктор. Подробнее об этом здесь . Поскольку функциональный компонент не имеет равных возможностей конструктора, использование ловушки для запуска кода только один раз перед монтированием компонента может иметь смысл в определенных случаях. Вы можете достичь этого с помощью пользовательского крючка.Тем не менее, есть подводный камень. Не используйте его для асинхронной установки вашего состояния (например, после запроса к серверу. Так как вы можете ожидать, что это повлияет на начальный рендеринг, что не будет). Такие случаи должны быть обработаны с
useComponentDidMount
.демонстрация
Полная демонстрация
источник
componentWillMount
основана наuseEffect
двух проблемах. Первый заключается в том, что в функциональных компонентах нет жизненного цикла монтирования, оба хуков будут работать после рендеринга компонента, поэтомуRuns only once before component mounts
вводит в заблуждение. Второе - это то, чтоcomponentWillMount
вызывается при рендеринге сервера, аuseEffect
это не так. Многие библиотеки по-прежнему полагаются,UNSAFE_componentWillMount
потому что в настоящее время это единственный способ вызвать побочный эффект на стороне сервера.По данным responsejs.org, компонентWillMount не будет поддерживаться в будущем. https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
Нет необходимости использовать componentWillMount.
Если вы хотите что-то сделать до монтирования компонента, просто сделайте это в конструкторе ().
Если вы хотите выполнять сетевые запросы, не делайте этого в componentWillMount. Это потому, что это приведет к неожиданным ошибкам.
Сетевые запросы могут быть выполнены в componentDidMount.
Надеюсь, поможет.
обновлено 08/03/2019
Причина, по которой вы запрашиваете componentWillMount, вероятно, заключается в том, что вы хотите инициализировать состояние перед рендерингом.
Просто сделайте это в useState.
или, может быть, вы хотите запустить функцию в componentWillMount, например, если ваш оригинальный код выглядит следующим образом:
с помощью hook, все, что вам нужно сделать, это удалить метод жизненного цикла:
Я просто хочу добавить что-то к первому ответу об использовании эффекта.
useEffect запускается для каждого рендера, это комбинация componentDidUpdate, componentDidMount и ComponentWillUnmount.
Если мы добавим пустой массив в useEffect, он будет запущен сразу после монтирования компонента. Это потому, что useEffect будет сравнивать массив, который вы ему передали. Так что это не должен быть пустой массив. Это может быть массив, который не изменяется. Например, это может быть [1,2,3] или ['1,2']. useEffect по-прежнему работает только при монтировании компонента.
От вас зависит, хотите ли вы, чтобы он запускался один раз или запускался после каждого рендера. Это не опасно, если вы забыли добавить массив, если знаете, что делаете.
Я создал образец для крючка. Пожалуйста, проверьте это.
https://codesandbox.io/s/kw6xj153wr
Обновлено 21/08/2019
Это был белый цвет, так как я написал ответ выше. Есть кое-что, на что, я думаю, нужно обратить внимание. Когда вы используете
Когда реакция сравнивает значения, переданные в массив [], он использует Object.is () для сравнения. Если вы передаете объект, например,
Это точно так же, как:
Он будет перерисовываться каждый раз, потому что когда Object.is () сравнивает объект, он сравнивает его ссылку, а не само значение. Это то же самое, что и то, почему {} === {} возвращает false, потому что их ссылки разные. Если вы все еще хотите сравнить сам объект, а не ссылку, вы можете сделать что-то вроде этого:
источник
useLayoutEffect
может выполнить это с помощью пустого набора наблюдателей ([]
), если функциональность на самом деле похожаcomponentWillMount
- он будет запущен до того, как первый контент попадет в DOM - хотя на самом деле есть два обновления, но они синхронны перед отображением на экране.например:
Преимущество по сравнению
useState
с инициализатором / установщиком илиuseEffect
то, что он может вычислить проход рендеринга, не приводит к фактическим повторным рендерингам в DOM, которые пользователь заметит, и он запускается до первого заметного рендеринга, что не относится к случаю.useEffect
, Недостатком является, конечно, небольшая задержка в вашем первом рендере, так как проверка / обновление должны выполняться перед рисованием на экране. Это действительно зависит от вашего варианта использования, хотя.Лично я думаю, что
useMemo
это хорошо в некоторых нишевых случаях, когда вам нужно сделать что-то тяжелое - если вы помните, что это исключение против нормы.источник
Вот как я симулирую конструктор в функциональных компонентах, используя
useRef
ловушку:Вот пример жизненного цикла:
Конечно, у компонентов класса нет
Body
шагов, невозможно выполнить симуляцию 1: 1 из-за различных концепций функций и классов.источник
Я написал пользовательский хук, который будет запускать функцию один раз перед первым рендерингом.
useBeforeFirstRender.js
Использование:
источник
Есть хороший обходной путь для реализации
componentDidMount
иcomponentWillUnmount
сuseEffect
.Основываясь на документации,
useEffect
можно вернуть функцию «очистки». эта функция не будет вызываться при первомuseEffect
вызове, только при последующих вызовах.Поэтому, если мы используем
useEffect
ловушку без каких-либо зависимостей, ловушка будет вызываться только тогда, когда компонент смонтирован, а функция очистки очищается, когда компонент размонтирован.Вызов функции очистки очистки вызывается только тогда, когда компонент отключен.
Надеюсь это поможет.
источник
useEffect
вызове вы получаете ту же функциональностьcomponentWillMount
иcomponentWillUnmount
в приятной и чистой формеuseEffect
запускается только после рендеринга, аcomponentWillMount
запускается до рендеринга компонента.componentDidMount
нетcomponentWillMount
. Я упустил это в вопросе, мой плохой.Вы можете взломать хук useMemo для имитации события жизненного цикла componentWillMount. Просто сделать:
Вам нужно будет сохранить ловушку useMemo, прежде чем что-либо, взаимодействующее с вашим состоянием. Это не так, как задумано, но у меня сработало для всех проблем componentWillMount.
Это работает, потому что useMemo не требует фактического возврата значения, и вам не нужно фактически использовать его как что-либо, но поскольку оно запоминает значение, основанное на зависимостях, которые будут выполняться только один раз ("[]"), и оно поверх нашего компонента, оно запускается один раз, когда компонент монтируется раньше всего.
источник
https://reactjs.org/docs/hooks-reference.html#usememo
источник
Ответ Бена Карпа мне кажется верным.
Но поскольку мы используем функциональные способы, от закрытия и HoC может выиграть еще один подход:
Тогда используйте это:
источник
Короткий ответ на ваш оригинальный вопрос, как
componentWillMount
можно использовать с React Hooks:componentWillMount
является устаревшим и считается наследием . Реакция рекомендации :Теперь в Hook FAQ вы узнаете, что такое эквивалент конструктора класса для компонентов функций:
Итак, пример использования
componentWillMount
выглядит следующим образом:источник
Просто добавьте пустой массив зависимостей в useEffect, в котором он будет работать
componentDidMount
.источник
Есть простой трюк для симуляции
componentDidMount
иcomponentWillUnmount
использованияuseEffect
:источник