ComponentDidMount для функции React / компонента хуков?

Есть ли способы имитировать componentDidMount в функциональных компонентах React с помощью хуков?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
200
0
95 832
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Вы хотите использовать useEffect(), который, в зависимости от того, как вы используете функцию, может действовать так же, как componentDidMount ().

Например. вы можете использовать настраиваемое свойство состояния loaded, для которого изначально установлено значение false, и переключить его на true при рендеринге и активировать эффект только при изменении этого значения.

Документация

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

Yangshun Tay 30.12.2018 00:10

В функциональных компонентах нет componentDidMount, но перехватчики React предоставляют способ эмуляции поведения с помощью перехватчика useEffect.

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

Пожалуйста, прочтите документация на useEffect.

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.info('componentDidMount');
  }, []);

  return (
    <div>
      <p>componentDidMount: {count} times</p>
      <button
        onClick = {() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src = "https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src = "https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

<div id = "app"></div>
Ответ принят как подходящий

Для стабильной версии хуков (React Version 16.8.0+)

Для componentDidMount

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

Для componentDidUpdate

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

Для componentWillUnmount

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

Итак, в этой ситуации вам нужно передать свою зависимость в этот массив. Предположим, у вас есть такое состояние

const [count, setCount] = useState(0);

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

useEffect(() => {
  // <div>{count}</div>
}, [count]);

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

Подробное объяснение! Есть ли способ имитировать componentDidReceiveProps?

jeyko 13.02.2019 19:44

Я не знаю об этом, даже если он существует. Вы можете проверить эту ветку на github.com/facebook/react/issues/3279

Mertcan Diken 13.02.2019 21:35

Спасибо за это, так как я не знал о втором аргументе в useState. Всем, кто читает это, имейте в виду, что оставление второго аргумента undefined приведет к срабатыванию вашего эффекта при каждом рендеринге (если я не ошибаюсь).

dimiguel 13.03.2019 20:17

Вы имеете в виду зависимости useEffect (передача массива зависимостей)? Если да, то, если вы оставите поле пустым, это ошибка в коде. Для деконструкции массива вам понадобятся оба параметра [count, setCount], потому что count - это ваша переменная состояния в этом примере, а setCount - ваша функция для обновления этого состояния.

Mertcan Diken 13.03.2019 20:25

Спасибо за ответ. Документация по этому поводу здесь responsejs.org/docs/hooks-effect.html

Josh 19.01.2020 17:05

Я пытался использовать пустой массив зависимостей для имитации componentDidMount. Проблема в том, что это обычно приводит к предупреждению: «React Hook useEffect имеет недостающую зависимость: <some prop>. Либо включите его, либо удалите массив зависимостей response-hooks / excustive-deps». Применение любого из предложенных «исправлений» заставляет его больше не вести себя как componentDidMount. Я делаю что-то неправильно?

Jonas Rosenqvist 06.08.2020 00:50

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

kca 20.12.2020 14:26

Ответ не утверждает, что он равен чему-либо, предложение заканчивается надеждой на то, что оно поможет. Так что я не вижу здесь ничего плохого. И, похоже, многим это помогло. Но я открыт для любых предложений по повышению надежности этого ответа, поскольку в этом вся цель. @kca

Mertcan Diken 21.12.2020 12:40

Это самая краткая документация по useEffect () в Интернете.

nonethewiser 09.04.2021 22:51

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

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

Возьмем, к примеру,

function App() {
  const [appointments, setAppointments] = useState([]);
  const [aptId, setAptId] = useState(1);

  useEffect(() => {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = aptId;
          console.info(aptId);
          setAptId(aptId + 1);
          return item;
        })
        setAppointments(apts);
      });
  }, []);

  return(...);
}

и

class App extends Component {
  constructor() {
    super();
    this.state = {
      appointments: [],
      aptId: 1,
    }
  }

  componentDidMount() {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = this.state.aptId;
          this.setState({aptId: this.state.aptId + 1});
          console.info(this.state.aptId);
          return item;
        });
        this.setState({appointments: apts});
      });
  }

  render(...);
}

Это только для примера. так что давайте не будем говорить о передовых методах работы или потенциальных проблемах с кодом. И то, и другое имеет одинаковую логику, но последнее работает только так, как ожидалось. Вы можете получить функциональность componentDidMount с запущенным useEffect в это время, но по мере роста вашего приложения есть вероятность, что вы МОЖЕТЕ столкнуться с некоторыми проблемами. Так что вместо того, чтобы переписывать на этом этапе, лучше сделать это на ранней стадии.

Кроме того, ООП не так уж и плох, если бы было достаточно процедурно-ориентированного программирования, у нас никогда не было бы объектно-ориентированного программирования. Иногда это больно, но лучше (технически не говоря уже о личных проблемах).

Я сделал это. У меня возникла проблема с использованием крючков. Проблема исчезла после преобразования его в класс.

Julez 21.09.2020 14:54

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

lawrence-witt 20.02.2021 02:36

точный эквивалентный крючок для componentDidMount () -

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

надеюсь, что это поможет :)

Не существует точного эквивалента для componentDidMount в перехватчиках реакции.


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

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

Решение 1:

useEffect(() => {
  console.info("I have been mounted")
}, [])

Решение 2:

const num = 5

useEffect(() => {
  console.info("I will only run if my deps change: ", num)
}, [num])

Решение 3 (с функцией):

useEffect(() => {
  const someFunc = () => {
    console.info("Function being run after/on mount")
  }
  someFunc()
}, [])

Решение 4 (useCallback):

const msg = "some message"

const myFunc = useCallback(() => {
  console.info(msg)
}, [msg])

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

Решение 5 (проявить творческий подход):

export default function useDidMountHook(callback) {
  const didMount = useRef(null)

  useEffect(() => {
    if (callback && !didMount.current) {
      didMount.current = true
      callback()
    }
  })
}

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

Источник (подробнее): Использование componentDidMount в перехватчиках реакции

Хук useEffect () позволяет нам достичь функциональности componentDidMount, componentDidUpdate функциональности componentWillUnMount.

Различный синтаксис useEffect () позволяет реализовать каждый из вышеперечисленных методов.

i) componentDidMount

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

ii) componentDidUpdate

useEffect(() => {
  //code here
}, [x,y,z]);

//where x,y,z are state variables on whose update, this method should get triggered

iii) componentDidUnmount

useEffect(() => {
  //code here
  return function() {
    //code to be run during unmount phase
  }
}, []);

Вы можете проверить официальный сайт реакции для получения дополнительной информации. Официальная страница React на хуках

Информация об асинхронных функциях внутри хука:

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

useEffect(() => {
  async function fetchData() {
    // You can await here
    const response = await MyAPI.getData(someId);
    // ...
  }
  fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick = {() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Посетите этот официальные документы. Очень легко понять последний способ.

https://reactjs.org/docs/hooks-effect.html

ComponentDidMount

useEffect(() => {
  //code here
}, []);
  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

Другие вопросы по теме