【问题标题】:How to delay redux state changes to allow for a side effect in a react component如何延迟 redux 状态更改以允许反应组件中的副作用
【发布时间】:2017-03-18 06:07:19
【问题描述】:

抱歉,标题含糊不清。解释我的问题的最佳方式可能是一个例子。

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

该基本功能有效,但现在我想向按钮添加反馈,以便当副作用成功时,它将标签更改为复选标记(为简单起见,如果请求,我将不做任何事情并保持列表不变在此示例中失败)。在从列表中删除之前,该项目将在带有复选标记的情况下多停留一秒钟。

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

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

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

以前有没有人处理过这样的问题?

谢谢

编辑:我认为它不应该真正改变一般解决方案,但我正在使用 redux-loop 来处理副作用。我觉得一个通用的解决方案可以很好地与 thunk 或 saga 或其他任何东西一起使用。

【问题讨论】:

  • 如果您还没有,请查看:stackoverflow.com/questions/35411423/…
  • 是的,我已经看到了。我的问题更多是关于如何以干净的方式重复执行此操作而不在任何地方重复逻辑的架构问题。例如,在 item reducer 中,我有逻辑来存储哪些按钮处于哪些状态。但我想避免在处理不同类型对象的单独减速器中重写这种逻辑。我想到的一件事可能是有一个通用的 buttonState reducer 来处理应用程序中所有按钮的状态。类似的东西。但我很想看看人们是否有首先奏效的解决方案。

标签: reactjs redux react-redux


【解决方案1】:

您提到您正在使用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>');
};

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

【讨论】:

  • 感谢您的帮助。我实现了与您描述的类似的东西。我认为理想情况下,react 将允许组件延迟其自己的卸载,这将简化这一点,因为它允许我在 reudx 中保持状态更新,并且只有按钮担心这个延迟卸载逻辑。但这没有实现,所以这是目前最好的选择。
【解决方案2】:

Ian 的解决方案应该可以很好地推广,但也许,如果您可以接受不需要 DOM 活动的成功确认:

一个简单的卸载样式,将元素变为绿色,然后将其淡出,足以让令人满意的用户反馈表明事情已经解决了。

【讨论】:

    猜你喜欢
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 2021-11-16
    • 2018-05-21
    相关资源
    最近更新 更多