关于 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?
如果它被立即调用,您将无法干净利落地执行上述操作:在 解析 获取或任何异步调用后调度后续操作。
据我了解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?
如果它被立即调用,您将无法干净利落地执行上述操作:在 解析 获取或任何异步调用后调度后续操作。