如何延迟redux状态更改以允许反应组件中的副作用

时间:2017-03-17 00:30:26

标签: reactjs redux react-redux

对不起那种模糊的标题。解释我的问题的最佳方式可能是一个例子。

我在redux中有一个项目,列表使用标准的react-redux连接组件显示在react组件中。每个单独的项目都有一个按钮,单击该按钮时会执行一些异步工作,然后从列表中删除该项目并将其放在另一个显示在其他位置的列表中。在redux中处理启动异步工作的逻辑非常重要,因为它对我的应用程序状态很重要。

基本功能有效,但现在我想向按钮添加反馈,这样当副作用成功时,它会将标签更改为Checkmark(为简单起见,我什么也不做,如果请求则保持列表不变在这个例子中失败了)。在从列表中删除之前,该项目将使用复选标记保持额外的秒数。

问题是,如果我在异步工作完成后立即从列表中删除该项,则会立即卸载它,因此我需要延迟它。我一直试图想出一种方法来实现可以在我的应用程序中重复使用的逻辑,因为我希望在应用程序的其他无关部分中使用复选标记反馈。

简单的解决方案是在成功时调度一个只更改状态以指示项目请求成功的操作,然后执行setTimeout以在1秒后调度另一个操作以实际从列表中删除该项目。

我觉得如果我在我的应用程序中的不同位置执行该逻辑将变得非常重复,我有一个按钮。我希望能够不必为每个需要它的新按钮重复超时逻辑。但我希望我的应用程序显示的内容代表我的应用程序的当前状态。

有人曾经处理过这样的问题吗?

由于

编辑:我认为它不应该真正改变一般解决方案,但我正在使用redux-loop来处理副作用。我觉得通用解决方案可以在thunk或saga或其他任何方面正常工作。

2 个答案:

答案 0 :(得分:2)

您提到您使用redux-loop来处理异步内容。我对redux-thunk比较熟悉,所以如果你对它好,我会给你一个使用thunk的答案。

如果您在操作创建者中设置了超时,则可以将代码保留为DRY,然后从多个按钮调用该操作创建者:

// actionCreators.js

const fetchTheThings = (url, successAction, failureAction, followUpAction) => (dispatch) => {

  //if you put the app in an intermediate state
  //while you wait for async, then do that here
  dispatch({ type: 'GETTING_THINGS' });

  //go do the async thing
  fetch(url)
    .then(res => {
      if (res.status === 200) return res.json();
      return Promise.reject(res);
    })
    .then(data => {
      //on success, dispatch an action, the type of which
      //you passed in as an argument:
      dispatch({ type: successAction, data });

      //then set your timeout and dispatch your follow-up action 1s later
      setTimeout(() => {
        dispatch({ type: followUpAction });
      }, 1000);
    })
    .catch(err => {
      //...and handle error cases
      dispatch({ type: failureAction, data: err });
    });
};

//then you can have exported action creators that your various buttons call
//which specify the action types that get passed into fetchTheThings()

export const actionFiredWhenButtonOneIsPressed = () => {
  return fetchTheThings('<some url>', '<success action>', '<failure action>', '<follow-up action>');
};

export const actionFiredWhenButtonTwoIsPressed = () => {
  return fetchTheThings('<other url>', '<other success action>', '<other failure action>', '<other follow-up action>');
};

希望至少能给你一些想法。祝你好运!

答案 1 :(得分:0)

Ian的解决方案应该可以推广,但也许,如果您能够获得不需要DOM活动的成功确认:

一个简单的卸载样式,将元素变为绿色,然后将其淡出,足以让满意的用户反馈告诉他们已经解决了这些问题。