即使提供了依赖项列表,useEffect无限循环

时间:2020-09-14 03:26:19

标签: reactjs react-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) && !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 getIntegrationStatusResult;
  };

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
});

我的代码有什么问题?如何停止无限循环?

3 个答案:

答案 0 :(得分:1)

通过创建具有三个可能值(未决,已实现和已拒绝)的新fetchStatus状态来解决问题,然后在我中添加fetchStatus === 'pending'的条件检查。

答案 1 :(得分:0)

我看到您正在对isEmpty进行答复,以检查是否应调用API。您可以检查isEmpty是否按预期工作,或者API始终返回空响应?

答案 2 :(得分:0)

该组件的预期功能是什么? API调用仅触发一次?

您的商店对isLoading标志的更新将在每次更改时导致渲染。目前,您的周期将是:

  • 初始渲染- fire API调用
  • 从标志渲染为true
  • 从标志更改为false的渲染- fire API调用
  • 无限期重复第2步和第3步

您是否已在控制台中记录了效果内的变量以及redux状态?如果Redux状态正在改变,则它会 在组件上触发渲染。

我认为最简单的解决方案是从依赖关系中删除isLoading标志,除非您有尝试实现的重试方案,但我正在寻找redux-saga的解决方案。