【问题标题】:React Redux Action Creator Dispatch Issue with Fetch API and Promise使用 Fetch API 和 Promise 反应 Redux Action Creator 调度问题
【发布时间】:2018-04-24 14:54:44
【问题描述】:

我正在 React 应用程序中编写动作创建器。当我进行一些 api 调用时,我需要在屏幕上显示 Progress Loader。所以,我的动作创建器看起来像这样。

export const fetchData = (actionType, param) => (dispatch) => {
  dispatch(Action(ActionConstants.SHOW_PROGRESS_LOADER)); // Show Loader Action
  return fetchDataRequest(actionType, param) // Here is Fetch APi Call
    .then(responseData => {
      dispatch(Action(ActionConstants.HIDE_PROGRESS_LOADER));
      dispatch(Action(recd(actionType), { data: responseData, receivedAt: Date.now() }));
    }).catch((error) => {
      dispatch(Action(ActionConstants.HIDE_PROGRESS_LOADER)); // Hide Loader Action
    });
};

当我编写这段代码时,它按预期工作,我将操作作为 dispatch(fetchData(data)) 从组件分派,并且我能够在我的父组件中显示加载器。我的理解是 fetch 正在向我返回承诺。获取完成后,我将隐藏按预期工作的加载程序。

现在,在某些情况下,我需要进行一些验证,而我不必进行任何 api 调用,但所有验证都在本地执行。 在这里我也想做同样的事情,就像我需要在我的父组件中显示加载器一样,当所有验证完成后我需要隐藏加载器。 我编写了相同的代码,即使操作被调用但我的渲染函数没有被调用。 我的代码如下:

// This my action creator which will actually do the validation
export const validateAndSaveData = () => {
  return ((dispatch, getState) => {
    return new Promise((resolve, reject) => {
      let saveRecommendDetailsFlag = true;
      // here i am dispacthing some action and storing data in my store
      saveRecommendDetailsFlag = canSaveData(getState());
      if (saveRecommendDetailsFlag) {
        resolve('SUCCESS');
      } else {
        reject('ERROR');
      }
    });
  });
};

还有一个动作创建者,我从 UI 组件调用它,它将首先启动显示加载器动作,然后执行验证,根据验证结果我必须隐藏加载器。

export const saveData = () => {
  return ((dispatch) => {
   dispatch(Action(ActionConstants.SHOW_PROGRESS_LOADER)); // Show Loader Action
    return dispatch(validateAndSaveData())
      .then(() => {
       // Here i m dispatching an action to do some more processing.
 dispatch(Action(ActionConstants.HIDE_PROGRESS_LOADER)); // Hide Loader Action
      })
      .catch(() => {
       dispatch(Action(ActionConstants.HIDE_PROGRESS_LOADER)); // Hide Loader Action
      });
  });
};

一切正常,但我的加载程序没有出现在屏幕上。我无法弄清楚我在哪里做错了。

谁能建议我如何解决这个问题? 我使用 setTimeout 函数得到了一些解决方法,但我认为这不是正确的方法。

export const saveData = () => {
  return ((dispatch) => {
   dispatch(Action(ActionConstants.SHOW_PROGRESS_LOADER)); // Show Loader Action
    setTimeout(()=>return dispatch(validateAndSaveData())
      .then(() => {
       // Here i m dispatching an action to do some more processing.
 dispatch(Action(ActionConstants.HIDE_PROGRESS_LOADER)); // Hide Loader Action
      })
      .catch(() => {
       dispatch(Action(ActionConstants.HIDE_PROGRESS_LOADER)); // Hide Loader Action
      });
},10);
  });
};

【问题讨论】:

  • 你有validateAndSaveDatavalidateAndSaveOverviewDetails,它们是同一个东西吗?如果没有,请发布validateAndSaveOverviewDetails的代码

标签: react-redux


【解决方案1】:

您的代码看起来很合理,我怀疑您的validateAndSaveData 承诺完成得如此之快,以至于屏幕上没有可见的加载程序。

在这种情况下,超时是完全合理的。但是,为了正确执行此操作,如果加载屏幕可见 + 如果显示时间足够长,我会保持状态。然后,您可以在加载屏幕都启动足够长的时间后移除加载屏幕,并且实际事件到期。

我不确定你使用的是哪个动作包,所以我不能发布确切的代码,但伪代码看起来像这样:

const delay = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds));


let loadingCounter = 0;
const showLoadingScreen = () => (dispatch) => {
  const counter = loadingCounter;
  loadingCounter++;

  delay(5).then(() => {
    if (getStore().loadingScreen.counter === counter) {
      dispatch(Action(ActionConstants.PROGRESS_LOADER_DELAY_ELAPSED))
    }
  })

  return dispatch(Action(ActionConstants.SHOW_PROGRESS_LOADER, counter))
}

基本上,您将跟踪加载程序的 3 个状态:

{
  counter: 0,
  taskCompleted: false,
  canHide: false,
}

计数器已保存,以便您可以消除在现有 SHOW_PROGRESS_LOADER 正在进行时收到 SHOW_PROGRESS_LOADER 时会发生的情况。 taskCompleted 会记录您正在等待的事情是否已完成,并且 canHide 会跟踪加载程序是否已在屏幕上显示足够长的时间。

当您发送PROGRESS_LOADER_DELAY_ELAPSED 时,它会将canHide 设置为true,而当您发送HIDE_PROGRESS_LOADER 时,它会将taskCompleted 设置为true。 (尽管您可能想要重命名后一个动作)。当canHidetaskCompleted 都设置为true 时,加载程序才能离开。

这是一种非常常见的 UI 模式 - 尝试快速完成一项任务。如果花费的时间超过很短的时间,则抛出一个加载对话框。但是,加载对话框保证保持最短时间以防止闪烁。因此,这种模式的更高级版本是添加另一个根本不显示进度加载器的状态,除非调用时间超过 Y 毫秒。

希望这是有道理的,如果没有,请发表评论:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2018-09-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2020-08-17
    • 1970-01-01
    相关资源
    最近更新 更多