我应该在哪里将同步副作用与redux中的操作相关联?

时间:2015-10-07 01:14:36

标签: javascript redux

(注意:我的问题没有写清楚,而且我正在考虑一些错误。当前版本的问题只是尝试编写一些可以使接受的答案对尽可能多的人有用的东西。)

我想要一个动作,将一个项目添加到商店并使用外部依赖项注册它。

我可以使用thunk中间件并编写

export function addItem(item) {
  return dispatch => {
    dispatch(_addItemWithoutRegisteringIt(item));
    externalDependency.register(item);
  };
}

但订阅者会在注册项目之前收到通知,他们可能会依赖于注册。

我可以撤销订单并写

export function addItem(item) {
  return dispatch => {
    externalDependency.register(item);
    dispatch(_addItemWithoutRegisteringIt(item));
  };
}

但是我通过一个唯一的id来跟踪外部依赖项中的项目,它只能在reducer中分配。

我可以在减速器中注册该项目,但我明白在减速器中做副作用是非常糟糕的形式,并可能导致问题。

那么最好的方法是什么?

(我的结论是:有许多方法可行,但对我的用例来说最好的方法是将句柄存储到Redux中的外部依赖项中,而不是外部依赖项中的Redux句柄。)

2 个答案:

答案 0 :(得分:10)

如果您使用Redux Thunk中间件,则可以将其封装在动作创建器中:

function addItem(id) {
  return { type: 'ADD_ITEM', id };
}

function showNotification(text) {
  return { type: 'SHOW_NOTIFICATION', text };
}

export function addItemWithNotification(id) {
  return dispatch => {
    dispatch(addItem(id));
    doSomeSideEffect();
    dispatch(showNotification('Item was added.');
  };
}

根据对此答案的评论进行阐述:

  

那么也许这是我案例的错误模式。我不希望在dispatch(addItem(id))doSomeSideEffect()之间调用订阅者。

在95%的情况下,您不应该担心订阅者是否被调用。如果数据没有改变,像React Redux这样的绑定不会重新渲染。

  

doSomeSideEffect()置于减速器中是一种可接受的方法,还是会有隐藏的陷阱?

不,将副作用放入reducer是绝对不可接受的。这违背了Redux的核心前提,并打破了其生态系统中的任何工具:Redux DevTools,{{3} },任何记录/重播解决方案,测试等。永远不要这样做。

如果您确实需要与动作一起执行副作用,并且您真的关心只有一次通知的订阅者,只需发送一个动作并使用[Redux Thunk]来“附加”副作用:

function addItem(id, item) {
  return { type: 'ADD_ITEM', id, item };
}

export function addItemWithSomeSideEffect(id) {
  return dispatch => {
    let item = doSomeSideEffect(); // note: you can use return value
    dispatch(addItem(id, item));
  };
}

在这种情况下,您需要处理来自不同缩减器的ADD_ITEM。没有两次通知订户就没有必要发送两个动作。

  

以下是我仍然无法理解的一点。 Dan建议thunk中间件不能推迟订阅者通知,因为这会破坏异步请求的常见用例。我仍然不明白这一点。

考虑一下:

export function doSomethinAsync() {
  return dispatch => {
    dispatch({ type: 'A' });
    dispatch({ type: 'B' });
    setTimeout(() => {
      dispatch({ type: 'C' });
      dispatch({ type: 'D' });
    }, 1000);
  };
}

您希望何时通知订阅?当然,如果我们仅在thunk退出时通知订阅者,我们根本不会通知他们CD

无论哪种方式,使用当前的中间件架构都是不可能的。中间件并不意味着阻止用户解雇。

然而,您所描述的内容可以使用Redux Undo等商店增强器来完成。它与Redux Thunk无关,但它会导致同步调度的任何一组动作被去抖。这样,您就会收到AB的一个通知,以及CD的另一个通知。那就是说在这种行为中写代码依赖在我看来会很脆弱。

答案 1 :(得分:1)

我还在学习Redux;然而,我的直觉是,对于某些custom middleware来说,这可能是一个潜在的候选人?