Хуки (часть-2) - useEffect

RedDeveloper
30.01.2023 13:25
Хуки (часть-2) - useEffect

React Hooks (часть-2) - useEffect

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

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

Рекомендуется прочитать предыдущий блог о useState before reading this one, так как он обеспечивает отличную основу для понимания того, как работает хук useEffect в отношении состояния. Мы также предоставим реальные примеры и объяснения, чтобы помочь вам освоить этот важный инструмент и улучшить производительность ваших React-приложений.

Что мы рассмотрим?

  • Побочные эффекты
  • (конечно)
  • Массив зависимостей
  • Функции очистки для useEffects

Что такое побочные эффекты?

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

Примерами таких побочных эффектов являются,

  • Выполнение ввода-вывода
  • Получение данных с сервера или API
  • Изменение нелокальной переменной и изменение статической локальной переменной
  • Виджеты сторонних производителей, сеть

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

Использовать UseEffect следующим образом:

  useEffect(()=>{

    //Run side effects here

  }, [
    //This is a dependency array
    //This is optional
  ])

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

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

const Useeffect = () => {
  const [counter, setCounter] = useState(0);

  useEffect(()=>{
    console.info("inside useEffect")
    //This will rerender after each button click.
  })

  const handleOnClick=()=>{
    console.info("Button Clicked")
    setCounter(counter+1);

  }
  return (
    <div>
      <button onClick = {handleOnClick} >Click me!</button>
      <h3>{counter}</h3>
    </div>
  )
}
Это простой компонент счетчика мы увеличиваем счетчик при каждом нажатии на кнопку После

Теперь мы хотим добавить функциональность для изменения цвета фона документа только в этом компоненте. Код будет выглядеть следующим образом:

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

const Example = () => {
  const [color, setColor] = useState("white");
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    console.info("inside useEffect")
    document.body.style.backgroundColor = color;
  });

  const handleOnClick = (e) => {
    e.preventDefault()
    setCounter(counter+1)
  };
  console.info("rendering")

  return (
    <div>
      <input
        type="text"
        onChange = {(e) => {
          setColor(e.target.value);
        }}
        name="color"
        value = {color}
      />
      <br style = {{margin:20}}/>
      <button onClick = {handleOnClick}>Click me!</button>
      <label>{counter}</label>
    </div>
  );
};
цвет фона был установлен на белый Когда пользователь вводит цвет цвет фона меняется

Что такое массив зависимостей?

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

useEffect(callback, dependency array)

Теперь давайте добавим массив зависимостей в приведенный выше код:

const Example = () => {
  const [color, setColor] = useState("white");
  const [counter, setCounter] = useState(0);

  //This is useEffect for changes the color of document
  useEffect(() => {
    console.info("inside useEffect1")
    document.body.style.backgroundColor = color;
  },[color]);
  //Here in the dependency array we have added the color state varaible
  //Whenever the color state changes then only this useEffect will run

  //In this useEffect we did not provide any depencency array
  useEffect(() => {
    console.info("inside useEffect2")
  });

  const handleOnClick = (e) => {
    e.preventDefault()
    setCounter(counter+1)
  };
  console.info("rendering")

  return (
    <div>
      <input
        type="text"
        onChange = {(e) => {
          setColor(e.target.value);
        }}
        name="color"
        value = {color}
      />
      <br style = {{margin:20}}/>
      <button onClick = {handleOnClick}>Click me!</button>
      <label>{counter}</label>
    </div>
  );
};
Теперь давайте добавим массив зависимостей в приведенный выше код

Как мы видим, только 2-й useEffect внутри компонента будет вызываться при нажатии на кнопку, а 1-й useEffect - при изменении входных данных, т.е. при изменении состояния цвета.

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

useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
}, []);

Будет получать данные из API , используя только один вызов.

Функция очистки UseEffect

Важно отметить, что хук useEffect по умолчанию будет выполняться при каждом рендере. Например, если данные из API извлекаются в то время, как пользователь переходит на другую страницу, извлечение данных будет продолжаться, даже если в них больше нет необходимости. Нам нужно прервать ее. Это можно сделать с помощью AbortController .

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

Код будет выглядеть следующим образом:

useEffect(() => {
  effect
  return () => {
    cleanup
  }
}, [input])

Рассмотрим на примере, как реализовать функцию очистки.

  useEffect(() => {
    const controller = new AbortController();
    //AbortController is a simple object 
    //that generates an 'abort' event on its 'signal' property 
    //when the abort() method is called.
    const signal = controller.signal;
  
    //We can pass this sinal as a option to the 'fetch', 
    //it will listen to it and we can abort the fetch request
     fetch("https://jsonplaceholder.typicode.com/users", {
        signal
      })
      .then((response) => response.json())
      .then((response) => {
        // handle success
        console.info(response);
      })
      .catch((err) => {
        if (err.name === 'AbortError') {
          console.info('successfully aborted');
        } else {
          // handle error
        }
      });
    return () => {
      // cancel the request before component unmounts
      controller.abort();
    };
  }, []);

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

Вот и все о useEffect. Если вы не читали блог о useState, пожалуйста, прочитайте его, нажав здесь . В следующем блоге мы рассмотрим useContext.

Спасибо, что прочитали эту статью, надеюсь, она помогла вам понять, как эффективно использовать хук useEffect.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?

20.08.2023 18:21

Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией

20.08.2023 17:46

В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox

19.08.2023 18:39

Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest

19.08.2023 17:22

В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!

Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️

18.08.2023 20:33

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL

14.08.2023 14:49

Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.