Как использовать componentWillMount () в React Hooks? - PullRequest
0 голосов
/ 25 ноября 2018

В официальных документах React упоминается -

Если вы знакомы с методами жизненного цикла класса React, вы можете думать об использовании Effect Hook как componentDidMount, componentDidUpdate и componentWillUnmount вместе взятых.

Мой вопрос - как мы можем использовать метод componentWillMount() lifecyle в ловушке?

Ответы [ 6 ]

0 голосов
/ 17 июля 2019

Я написал пользовательский хук, который будет запускать функцию один раз перед первым рендерингом.

useBeforeFirstRender.js

import { useState, useEffect } from 'react'

export default (fun) => {
  const [hasRendered, setHasRendered] = useState(false)

  useEffect(() => setHasRendered(true), [hasRendered])

  if (!hasRendered) {
    fun()
  }
}

Использование:

import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'


export default () => (
  useBeforeFirstRender(() => {
    console.log('Do stuff here')
  })

  return (
    <div>
      My component
    </div>
  )
)
0 голосов
/ 29 июня 2019

useComponentDidMount hook

В большинстве случаев useComponentDidMount - это инструмент для использования.Он будет запущен только один раз после монтирования компонента (начальный рендеринг).

 const useComponentDidMount = func => useEffect(func, []);

useComponentWillMount

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

const useComponentWillMount = func => {
  const willMount = useRef(true);

  if (willMount.current) {
    func();
  }

  useComponentDidMount(() => {
    willMount.current = false;
  });
};

Однако здесь есть подводный камень.Не используйте его для асинхронной установки вашего состояния (например, после запроса к серверу. Так как вы можете ожидать, что это повлияет на начальный рендеринг, который не будет).Такие случаи должны быть обработаны с useComponentDidMount.

Демо

const Component = (props) => {
  useComponentWillMount(() => console.log("Runs only once before component mounts"));
  useComponentDidMount(() => console.log("Runs only once after component mounts"));
  ...

  return (
    <div>{...}</div>
  );
}

Полная демонстрация

0 голосов
/ 20 апреля 2019

useLayoutEffect может выполнить это с пустым набором наблюдателей ([]), если функциональность на самом деле похожа на componentWillMount - он запустится до того, как первый контент попадет в DOM - хотя на самом деле их дваобновления, но они синхронны перед отображением на экране.

, например:


function MyComponent({ ...andItsProps }) {
     useLayoutEffect(()=> {
          console.log('I am about to render!');
     },[]);

     return (<div>some content</div>);
}

Преимущество по сравнению с useState с инициализатором / установщиком или useEffect заключается в том, что оно может вычислитьпроход рендеринга, нет фактических повторных рендеров в DOM, которые пользователь заметит, и он запускается до первого заметного рендера, что не имеет место для useEffect.Недостатком является, конечно, небольшая задержка вашего первого рендера, так как проверка / обновление должны выполняться перед рисованием на экране.Это действительно зависит от вашего варианта использования, хотя.

Я лично думаю, что useMemo хорошо в некоторых нишевых случаях, когда вам нужно сделать что-то тяжелое - если вы помните, что это исключение по сравнению с нормой.

0 голосов
/ 10 февраля 2019

https://reactjs.org/docs/hooks-reference.html#usememo

Помните, что функция, переданная useMemo, запускается во время рендеринга.Не делайте там ничего, что вы обычно не делаете во время рендеринга.Например, побочные эффекты принадлежат useEffect, а не useMemo.

0 голосов
/ 25 ноября 2018

Вы не можете использовать в ловушке ни один из существующих методов жизненного цикла (componentDidMount, componentDidUpdate, componentWillUnmount и т. Д.). Они могут использоваться только в компонентах класса.А крючки вы можете использовать только в функциональных компонентах.Что ниже в строке из документа React

Если вы знакомы с методами жизненного цикла класса React, вы можете подумать об использовании Effect Hook как componentDidMount, componentDidUpdate и componentWillUnmount вместе.

предполагает, что вы можете имитировать этот метод жизненного цикла из компонента класса в функциональных компонентах.

Код внутри componentDidMount запускается один раз, когда компонент монтируется.Эквивалент крючка useEffect для этого поведения равен

useEffect(() => {
  // Your code here
}, []);

Обратите внимание на второй параметр здесь (пустой массив).Это будет выполняться только один раз.

Без второго параметра ловушка useEffect будет вызываться при каждом рендеринге компонента, который может быть опасным.

useEffect(() => {
  // Your code here
});

componentWillUnmount isиспользовать для очистки (например, удаление списков событий, отмена таймера и т. д.).Допустим, вы добавляете список событий в 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', () => {})
  }
}, [])
0 голосов
/ 25 ноября 2018

В соответствии сactjs.org, componentWillMount не будет поддерживаться в будущем.https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

Нет необходимости использовать componentWillMount.

Если вы хотите что-то сделать до монтирования компонента, просто сделайте это в конструкторе ().

ЕслиВы хотите делать сетевые запросы, не делайте этого в componentWillMount.Это потому, что это приведет к неожиданным ошибкам.

Сетевые запросы можно выполнять в componentDidMount.

Надеюсь, это поможет.


обновлено 08.03 2019

Причина, по которой выСпросите для componentWillMount, вероятно, потому что вы хотите инициализировать состояние перед рендерингом.

Просто сделайте это в useState.

        const helloWorld=()=>{
           const [value,setValue]=useState(0) //initialize your state here
            return <p>{value}</p>
            }
         export default helloWorld;

или, возможно, вы хотите запустить функцию в componentWillMount, например,если ваш оригинальный код выглядит так:

  componentWillMount(){
    console.log('componentWillMount')
    }

с крючком, все, что вам нужно сделать, это удалить метод жизненного цикла:

    const hookComponent=()=>{
       console.log('componentWillMount')
       return <p>you have transfered componeWillMount from class component into hook </p>
    }

Я просто хочу добавить что-то в первыйответ об useEffect.

useEffect(()=>{})

useEffect запускается на каждом рендере, это комбинация componentDidUpdate, componentDidMount и ComponentWillUnmount.

 useEffect(()=>{},[])

Если мы добавим пустой массив в useEffect, он будет запущен толькокогда компонент установлен.Это потому, что useEffect будет сравнивать массив, который вы передали ему.Таким образом, это не должен быть пустой массив. Это может быть массив, который не изменяется.Например, это может быть [1,2,3] или ['1,2'].useEffect по-прежнему выполняется только при монтировании компонента.

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

Я создал пример для ловушки.Пожалуйста, проверьте это.

https://codesandbox.io/s/kw6xj153wr


обновлено 21/08/2019

С тех пор, как я написал, он был белымответ выше.Есть кое-что, на что, я думаю, нужно обратить внимание.Когда вы используете

useEffect(()=>{},[])

Когда реагирует, сравнивает значения, которые вы передали в массив [], он использует Object.is () для сравнения.Если вы передадите ему объект, такой как

useEffect(()=>{},[{name:'Tom'}])

Это точно так же, как:

useEffect(()=>{})

Он будет рендериться каждый раз, потому что когда Object.is () сравниваетобъект, он сравнивает свою ссылку, а не само значение.Это то же самое, что и то, почему {} === {} возвращает false, потому что их ссылки разные.Если вы все еще хотите сравнить сам объект, а не ссылку, вы можете сделать что-то вроде этого:

useEffect(()=>{},[JSON.stringify({name:'Tom'})])
...