关于 Redux-thunk,如果一个 handler 派发一个要调用的函数,为什么不直接调用呢?

About Redux-thunk, if a handler dispatches a function to be called, why not call it directly?

据我了解redux-thunk,可以

<button onClick={fn1}>Click Me</button>

而在fn1中,它调度的不是一个动作对象,而是调度一个函数fn2,这样当redux-thunk中间件调用它时(意思是fn2) ,调用 fetch 或 Ajax 调用,并让 then 履行处理程序或 Ajax 的回调分派一个操作对象,例如

{ type: "DATA_RECEIVED", data: data }

但是为什么fn1不直接调用fn2来完成任务,而是让中间件调用呢?

Redux Thunk 是一个 非常 瘦中间件(像 14 行瘦),它引入了 Redux 应该知道如何处理的约定为您异步处理。

你说

the thing is you do want fn2 to fire immediately. Such as: user clicks a button to fetch something, you do want the function that does the fetch or Ajax to fire immediately. I think with redux-thunk, if you dispatch a function, it is fired immediately

你是对的,你 希望它立即触发,但你想成为手动连接调用函数并传递调度的人还是你想让 Redux Thunk 帮你做吗?

无论如何,Redux 都需要在稍后的某个时间派发一个动作。 Redux Thunk 为您完成 "later"。

考虑这些差异:

const store = {
  dispatch() {
    console.log("Dispatch");
  }
};

// Action creator that retuns an action
const inc = () => ({
  type: "INCREMENT"
});

// Impure action creator that you shouldn't use
const badAsyncInc = () => {
  setTimeout(() => {
    store.dispatch({
      type: "INCREMENT"
    });
  }, 1000);
};

// Action creator that returns a function that takes dispatch as arg
const aInc = () => dis => setTimeout(() => dis({
  type: "INCREMENT"
}), 1000);

/*
 * The following will do everything including waiting to dispatch
 * and dispatching to the store.  That's good, but not good for
 * when we want to use a different store.
 */
badAsyncInc()();

/*
 * The following is the "manual" way of wiring up the delayed
 * dispatch that you have to do without Redux Thunk.
 */
aInc()(store.dispatch);

/*
 * With Redux Thunk, this will call the "fn2" immediately but also
 * pass the dispatch function to "fn2" for you so that you don't 
 * have to wire that up yourself.
 */
store.dispatch(aInc);

在这种情况下,您只需调用 badAsyncInc 即可完成,因为它会为您调用 store.dispatch。但是,如果您有多家商店怎么办?如果您想使用测试工具商店怎么办?如果你想完全模拟商店怎么办?您的 badAsyncInc 现在与商店结合在一起,这对动作创作者不利。

或者,您可以自己调用 aInc 并向其传递一个调度函数。但是,当您所有其他动作创建者可能被写为 store.dispatch(actionCreator()) 时,为什么要这样做呢? Redux Thunk 可以帮助您保持这种模式,即使是异步操作也是如此。

Redux Thunk 试图帮助您编写松散耦合且可测试的动作创建器。

in fn1, it dispatches not an action object, but dispatches a function fn2

调度函数背后的动机是该函数包含一个调度参数(由 Redux Thunk 提供)供您使用。

这里有一个例子,说明使分派变得可用有多强大:

const action = (url) => async (dispatch) => {
    try {
        const response = await fetch(url);
        dispatch(success(response));
    } catch (error) {
        dispatch(failure(error));
    }
}

Dispatch 使您能够为 reducer 处理成功或失败的操作。

更多详情: https://redux.js.org/advanced/async-actions/#async-action-creators

if a handler dispatches a function to be called, why not call it directly?

如果它被立即调用,您将无法干净利落地执行上述操作:在 解析 获取或任何异步调用后调度后续操作。