Рубрики
Без рубрики

Эбоаксиэффективные и умирающие крючки реагирования

Отказ от ответственности: Это не базовое введение в крючки. Там много великих учебников … Теги с JavaScript.

Отказ от ответственности: Это не базовое введение в крючки. Есть много отличных учебников, которые покрывают эту часть, как Реагистрировать документы самих себя.

В рамках младшей инженерной программы в 99designs я сделал немного глубокого погружения в Useffect и Уместите крючки реагирования.

Для меня было довольно интересно узнать на тему, с которой я был относительно знакомым (я использовал оба этих крючка рубцов), и чтобы увидеть, насколько все еще было то, что я еще не правильно понимал.

Моя отправная точка была Почему вещей. Я посмотрел через оригинальную мотивацию за помощью введения крючков, Useffect и Уместите В основном. Вы можете найти этот док здесь Отказ

ПОЧЕМУ USEFFECT?

Основная мотивация позади введения Useffect Крюк состояла в том, чтобы сделать сложные компоненты проще для управления и прочитаны.

Крючки позволяют разбить один компонент в меньшие функции на основе того, какие части связаны.

До Useffect крючок и Функциональные компоненты были введены, стандартный способ управления побочные эффекты внутри Компоненты класса были методы жизненного цикла.

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

Здесь вы можете увидеть очень концептуальный пример этой проблемы:

 componentDidMount() {
    // do x immediately after component has mounted 
    // also do y immediately after component mounted
 }
 componentDidUpdate() {
    // only do y when component has updated (but not on initial render)
 }
 componentWillUnmount() {
    // cleanup x immediately before component has unmounted
 }

Вы можете увидеть, что наш код повсюду. ComponentDidmount Содержит логику, связанную с функциональными возможностями x И y , пока ComponentDidupdate Просто содержит логику, связанную с функциональными возможностями y , а также ComponentWillunmount С другой стороны снова содержит логику, связанную только с х Отказ Это делает код трудно читать и тестировать, как я упоминал ранее.

Так что наш Useffect Крюк, который помогает нам решить эту проблему с гораздо более чистым подходом, который позволяет нам разделить нашу логику на основе что вещей, а не Когда Отказ

По умолчанию Useffect Запускается после первого визуализации и после каждого обновления, так что в основном после каждого визуализации, чтобы упростить его.

Давайте вернемся к нашему концептуальному примеру до и посмотрим, как Useffect решает нашу ранее описанную проблему.

useEffect(() => {
   // do x immediately after component has mounted
   // cleanup x immediately before component has unmounted
}, [])
useEffect(() => {
   // only do y when component has updated (but not on initial render)
}, [])

Вы можете увидеть, как мы теперь можем группировать на основе разных вещей, которые происходят и х и y больше не смешаются и перепутаны.

Результат: легче прочитать и намного проще тестировать.

На данный момент также стоит отметить, что реагируют настоятельно рекомендуют вам использовать несколько эффектов в вашем компоненте, если у вас много разных вещей. Так что не волнуйтесь, если вы окажетесь с 3 разными Useffect Внутри вашего компонента на самом деле считается хорошей практикой.

Массив зависимостей использования

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

Реагирование ввело массив зависимостей для повышения производительности. Как работает, это относительно простым, если вы работаете с примитивными значениями, такими как логические , Числа или Строки Отказ Есть три сценария, которые вы можете создать:

1. Не прохождение массива зависимости – не совсем рекомендуется

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

useEffect(() => {
    // no dependency array - runs on every re-render
})

2. Передача пустой массив зависимости

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

useEffect(() => {
    // empty dependency array - effect has NO dependencies and never re-runs
}, [])

3. Передача значений к вашим массиве зависимостей – вероятно, самый используемый в случае

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

useEffect(() => {
    // dependency array with values - if one of the values has changed, 
    // effect will re-run
}, [value1, value2])

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

Причина, по которой сложные значения не работают так же, как примитивные значения, лежит в пути реагирования, или, скорее, JavaScript обрабатывает эти значения. Под капотом отреагируйте реакцию Объект. Метод Отказ

Так что же это означает точно?

Когда у вас есть объект, массив или функция в вашем компоненте (независимо от того, является ли это переменной или реквизиты состояния) React хранит ссылку на этот объект в памяти (например, адрес, где этот объект живет в памяти).

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

Как следствие, когда Rect сравнивает значение, которое вы передали на массив зависимости в вашем Useffect , к оригинальному, они не будут одинаковыми, потому что их «адрес» в памяти изменились на перенастройке и, таким образом, даже если ваше значение не было обновлено, ваш эффект снова пробежал снова и снова, потому что Два значения ссылаются на другой объект в памяти (даже если вам выглядят одинаково).

Давайте посмотрим на пример:

const Team = ({ team }) => {
  const [players, setPlayers] = useState([])

  useEffect(() => {
    if (team.active) {
      getPlayers(team.id).then(setPlayers)
    }
  }, [team])

  return 
}

Итак, давайте скажем, у вас есть объект, который вы проходите к вашему компоненту как реквизиты. Здесь у нас есть Команда Компонент, который принимает в команда Объект, который выглядит так:

const team = {
    id: 1,
    name: 'Bulldogs',
    active: true
}

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

Поэтому, когда вы передаете его на свой массив зависимости, и ReCT проверяет, изменился ли этот объект или нет, и следует ли запускать эффект снова или нет, сравнение вернет ложь вызывая эффект повторно проработать на каждом повторном рендере.

Так что вы можете сделать, чтобы избежать этого? Есть несколько возможных подходов, и я просто перечисляю несколько из них.

1. Пройти только то, что вам действительно нужно и использовать в вашем useffect. крюк:

Давайте посмотрим на нашу командный компонент снова:

const Team = ({ team }) => {
  const [players, setPlayers] = useState([])

  useEffect(() => {
    if (team.active) {
      getPlayers(team.id).then(setPlayers)
    }
  }, [team.id, team.active])

  return 
}

Внутри нашего эффекта мы действительно просто используем свойства от объекта нашей команды, а именно Team.active а также Team.id которые снова являются примитивными ценностями.

В результате мы можем просто передавать эти точные значения на наш массив зависимости и, таким образом, избегать всех осложнений ссылок/сравнения адресов, упомянутых выше. Теперь наш эффект будет только повторно запустить, если Team.id или Team.active изменились.

2. Воссоздайте объект, чтобы использовать внутри нашего эффекта:

Давайте посмотрим на другой пример и предположим, что по какой-то причине нам нужны все команда объект в нашем Useffect А также в нашем компоненте.

const Team = ({ id, name, active }) => {
  const [players, setPlayers] = useState([])

  useEffect(() => {
    const team = { id, name, active }

    if (team.active) {
      getPlayers(team).then(setPlayers)
    }
  }, [id, name, active])

  const team = { id, name, active }

  return 
}

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

3. Мемузация – последнее средство:

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

const Team = ({ id, name, active }) => {
  const team = useMemo(() => createTeam({ id, name, active }), [
    id,
    name,
    active,
  ])
  const [players, setPlayers] = useState([])

  useEffect(() => {
    if (team.active) {
      getPlayers(team).then(setPlayers)
    }
  }, [team])

  return 
}

Будьте в курсе, хотя использование этого крючка вполне дорого, поэтому вы должны подумать дважды, прежде чем использовать его. Вы можете узнать больше о Угемер крюк здесь Отказ

Очистка вашего эффекта

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

Способ перейти в это должен вернуть функцию от вашего эффекта, который будет действовать в качестве очистки.

const Team = ({ team }) => {
  const [players, setPlayers] = useState([])

  useEffect(() => {
    if (team.active) {
      getPlayers(team.id).then(setPlayers)
    }
    subscribePlayers(players)

    return  (() => unsubscribePlayers(players)) // 'cleans up' our subscription
  }, [team.active, team.id])

  return 
}

Зачем умирать?

Очень простой способ, Уместите Позволяет добавить состояние React для функционирования компонентов (например, SetState для компонентов класса).

Немного наконечника при использовании этого крюка: разделение состояния в несколько переменных состояний на основе которых значения, как правило, могут меняться (особенно полезны при работе с объектами или массивами) и использовать его для простого государственного управления.

Если все станет более сложным в том, как вы управляете государством, для этого есть другие инструменты.

Пока я не нашел Уместите как сложный, как useffect. , есть некоторые важные характеристики, чтобы иметь в виду при работе с ним:

1. Обновление переменной состояния с Уместите Крюк всегда заменяет эта переменная вместо того, чтобы объединить ее (как делает setState). Это довольно важно, когда вы имеете дело с объектами или массивами, например.

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

const [team, setTeam] = useState(team)

setTeam({
    ...team,
    team.active: false
})

2. Это асинхронно. Вполне важно иметь в виду, что когда вы вызываете свою функцию, которые устанавливают состояние (например Setteam , например), он ведет себя асинхронно, поэтому он просто добавляет ваш запрос на обновление стоимости в очередь, и вы можете не увидеть результата немедленно.

Вот где Useffect Крюк приходит очень удобно и позволяет получить доступ к вашей обновленной переменной состояния немедленно.

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

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

const [count, setCount] = useState(0)

setState(prevState => prevState + 1)

4. Только звоните Уместите на верхнем уровне. Вы не можете назвать его в петлях, условиях, вложенных функциях и т. Д. Когда у вас есть несколько Уместите Звонки, порядок, в котором они вызывают, должны быть одинаковыми между рендеррами.

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

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

Оригинал: “https://dev.to/enitschorn/react-s-useeffect-usestate-hooks-55fe”