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

#reactjs #react-redux

#reactjs #реагировать-redux

Вопрос:

Я пытаюсь создать страницу запроса, используя redux, axios и API. В useEffect() , если переменная из useSelector пуста, а isLoading состояние false равно, тогда я выполняю запрос API. Однако даже без каких-либо изменений в этих переменных (уже в списке зависимостей), useEffect продолжает выполнять запрос API на неопределенный срок).

И при проверке состояния я вижу, что все время integrationStatusLoading меняется с true на false . Кажется, что useEffect запускается несколько раз даже до завершения предыдущего запуска.

Мой редуктор:

 import * as spreadsheetActions from './spreadsheetActions';

export const INITIAL_STATE = {
  messagesLog: [],
  loading: false,
  modalIsOpen: false,
  integration: {
    rows: [],
    loading: false
  }
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case spreadsheetActions.SET_INTEGRATION_STATUS:
      return { ...state, integration: {
        ...state.integration,
        rows: action.payload
      }};
    case spreadsheetActions.SET_LOADING_INTEGRATION_STATUS:
      return { ...state, integration: {
        ...state.integration,
        loading: action.payload
      }};
    default:
      return state;
  }
};
  

jsx:

   const IntegrationStatusContainer = function() {
  const classes = useStyles();
  const dispatch = useDispatch();
  const integrationStatusData = useSelector(state => state.spreadsheet.integration.rows);
  const integrationStatusLoading = useSelector(state => state.spreadsheet.integration.loading);

  useEffect(() => {
    if (isEmpty(integrationStatusData) amp;amp; !integrationStatusLoading) {
      dispatch(spreadsheetOperations.getIntegrationStatus());
    }
  }, [dispatch, integrationStatusData, integrationStatusLoading]);

  return (
    <IntegrationStatusTable items={integrationStatusData} isLoading={integrationStatusLoading} />
  );
};

export default IntegrationStatusContainer;
  

spreadsheetOperations.js

 export const getIntegrationStatus = () => async dispatch => {
  dispatch(spreadsheetActions.setLoadingIntegrationStatus(true));

  let response = await spreadsheetManager.getIntegrationStatus();

  batch(() => {
    dispatch(spreadsheetActions.setLoadingIntegrationStatus(false));
    dispatch(spreadsheetActions.setIntegrationStatus(response));
  });
};
  

spreadsheetManager.js

 getIntegrationStatus = async () => {
    const getIntegrationStatusResult = await spreadsheetService.getIntegrationStatus();
    return getIntegrationStatusResu<
  };
  

spreadsheetService.js

 getIntegrationStatus = async () => {
    const integrationStatusResponse = await axios.get(
      `${BASE_URL}/api/integration_status`
    );
    return integrationStatusResponse.data;
  };
}
  

spreadsheetActions.js

 export const setIntegrationStatus = rows => ({
  type: SET_INTEGRATION_STATUS,
  payload: rows
});

export const setLoadingIntegrationStatus = status => ({
  type: SET_LOADING_INTEGRATION_STATUS,
  payload: status
});
  

Что не так с моим кодом? Как я могу остановить бесконечный цикл?

Ответ №1:

Проблема решена путем создания нового fetchStatus состояния с тремя возможными значениями (ожидание, выполнено и отклонено), затем в моем if я добавил проверку условий для fetchStatus === 'pending' .

Ответ №2:

Я вижу, что вы отвечаете на isEmpty, чтобы проверить, следует ли вызывать API. Можете ли вы проверить, работает ли isEmpty как ожидалось, или API всегда возвращает пустой ответ?

Комментарии:

1. В настоящее время API всегда возвращает пустой массив, но это потому, что в базе данных нет строк.

Ответ №3:

Какова ожидаемая функциональность этого компонента? Что вызов API запускается только один раз?

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

  • Начальный рендеринг — вызов fire API
  • Рендеринг с изменением флага на true
  • Рендеринг с изменением флага на false — запуск вызова API
  • Повторяйте шаги 2 и 3 бесконечно

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

Я думаю, что самое простое решение — удалить флаг isLoading из зависимостей, если у вас нет сценария повторной попытки, которого вы пытаетесь достичь, но я бы посмотрел на redux-saga для решения этого.

Комментарии:

1. Точно. Я хочу, чтобы он срабатывал только один раз. Я попробовал пустой массив ( [] ) в списке зависимостей, однако React жалуется на это и сообщает, что мне нужно поместить dispatch и эти переменные туда. И да, я зарегистрировался на консоли, и integrationStatusLoading продолжает меняться.

2. Я думаю, вам просто нужно скопировать этот список зависимостей. В идеале все это, но я раньше не использовал react hooks, и, возможно, вам нужно сохранить отправку там. Конечно, наличие флага isLoading будет просто продолжать забивать его! Можете ли вы опубликовать, что происходит, когда вы удаляете все зависимости, кроме отправки?