ReactJS: как вызвать ловушку useEffect только один раз, чтобы получить данные API - PullRequest
2 голосов
/ 03 апреля 2019

Используя React, у меня есть следующий функциональный компонент, в котором я использую useEffect():

import React, { useEffect } from 'react';
import { connect } from 'react-redux';

const MessagingComponent = React.memo(({ loadMessages, messages, ...props }) => {

  useEffect(() => {
    loadMessages();
  });

  return <div {...props}>These are the messages</div>;
});

const mapDispatchToProps = dispatch => ({
  loadMessages: () => dispatch({ type: 'LOAD_MESSAGES' })
});

const mapStateToProps = state => {
  return {
    messages: state.chatt.messages.chatMessages
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MessagingComponent);

Как видите, у меня есть обратный вызов эффекта, который вызывает функцию loadMessages() в useEffect() обратный вызов в моем MessagingComponent:

  useEffect(() => {
    loadMessages();
  });

Вызов loadMessages() загружает сообщения, что вызывает повторную визуализацию компонента.Такое поведение является ожидаемым, однако проблема заключается в том, что при повторном рендеринге снова запускается хук useEffect(), что вызывает повторный вызов loadMessages().Это, в свою очередь, загружает сообщения из серверной части и вызывает повторную визуализацию компонента, и цикл повторяется.

Как я могу избежать этого?Стоит ли просто вставить условие if в хук useEffect() и проверить свойство messages?

Ответы [ 2 ]

4 голосов
/ 03 апреля 2019

Если я правильно понимаю, вы хотите имитировать поведение «при монтировании на компоненте» обычных реагирующих компонентов на основе классов через useEffect(), чтобы обратный вызов эффекта срабатывал только один раз при первом рендеринге.

Чтобы добиться такого поведения, вы можете передать пустой массив второму аргументу useEffect(), например, так:

useEffect(() => {
  loadMessages();
}, []); /* <-- add this */

Второй аргумент массива позволяет вам указать, какие prop переменные вызывают обратный вызов userEffect() (если есть) при изменении их значений.

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

Для получения дополнительной информации по этому второму аргументу см. Эту документацию и эту документацию

0 голосов
/ 25 мая 2019

useEffect() - это реагирующая перехват для функциональных компонентов, которая охватывает функциональные возможности перехватчиков жизненного цикла компонентов класса. useEffect() объединяет componentDidMount(), componentDidUpdate() и componentWillUnmount() компонентов класса, что означает, что он будет выполняться при монтировании компонента, при изменении состояния компонента и при отключении компонента из DOM.

Проверьте ниже пример,

useEffect(() => {
   setTimeout(() => {
      alert("data saved");
    }, 1000);
});

Выше код / ​​предупреждение выполняется, когда компонент смонтирован / начальный рендеринг, когда состояние компонента изменяется и когда компонент размонтирован из DOM.

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

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

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, [props.persons]);

Это выполнит код во время начального рендеринга и при изменении props.persons.

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

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, []);

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

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