8

(注意:我的问题没有写清楚,我在想一些错误的事情。当前版本的问题只是试图写一些可以使接受的答案对尽可能多的人有用的东西。)

我想要一个将项目添加到商店并将其注册到外部依赖项的操作。

我可以使用 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 中。)

4

2 回答 2

10

如果你使用Redux Thunk中间件,你可以将它封装在一个 action creator 中:

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

根据对此答案的评论进行详细说明:

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

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

放入doSomeSideEffect()减速器是一种可接受的方法还是有隐藏的陷阱?

不,将副作用放入减速器是绝对不能接受的。这违背了 Redux 的核心前提,并且破坏了其生态系统中的几乎所有工具:Redux DevToolsRedux Undo、任何记录/重放解决方案、测试等。永远不要这样做。

如果你真的需要与一个动作一起执行副作用,并且你真的很关心订阅者只被通知一次,那么只需调度一个动作并使用 [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);
  };
}

您希望何时通知订阅?C当然,如果我们只在 thunk 退出时通知订阅者,对于and ,我们根本不会通知他们D

无论哪种方式,这对于当前的中间件架构都是不可能的。中间件并不是为了防止订阅者被解雇。

但是,您所描述的可以使用像redux-batched-subscribe这样的存储增强器来完成。它与 Redux Thunk 无关,但它会导致同步调度的任何一组操作被去抖动。这样,您将收到一个关于Aand的通知B,以及另一个关于Cand的通知D。也就是说,在我看来,依赖这种行为编写代码会很脆弱。

于 2015-10-09T10:49:47.933 回答
1

我还在学习 Redux 的过程中;但是我的直觉说这可能是某些自定义中间件的潜在候选者?

于 2015-10-07T08:51:04.113 回答