Redux Thunk - 为什么我必须调用 dispatch() 两次?
Redux Thunk - Why do I have to call dispatch() twice?
请注意,我正在用 dispatch()
呼叫 setStepPositionIndex()
。当我删除 dispatch(...)
变成 setStepPositionIndex()
我希望 setStepPositionIndex()
中的调度调用会接收它传递的普通操作对象并调度它...
或者,如果我删除 setStepPositionIndex()
中的 dispatch()
调用(并保留 dispatch(setStepPositionIndex()
),同时显式返回普通 actionObj
在其中,我希望使用 dispatch(setStepPositionIndex(actionObj))
成功发送
但是成功执行此动作创建者需要两者...为什么?
/* actions.js */
import { store } from "../store.js";
store.dispatch(setStepPositionIndex());
export const SET_STEP_POSITION_INDEX = "SET_STEP_POSITION_INDEX";
export const setStepPositionIndex = () => {
return (dispatch, getState) => {
const newSteps = getState().goals.currentGoalSteps.map((stepObj, index) => {
return { ...stepObj, positionIndex: index };
});
console.log("newSteps", newSteps);
/* [{step: "Step3", positionIndex: 0}
{step: "Step2", positionIndex: 1}
{step: "Step1", positionIndex: 2}] */
const actionObj = {
type: SET_STEP_POSITION_INDEX,
stepsArr: newSteps
};
// Unsuccessful alone ->
// return actionObj
// unsuccessful alone (removing dispatch() wrapper from setStepPositionIndex
//->
return dispatch(actionObj);
};
};
/*Reducer.js*/
import * as actions from "../Actions/actions";
import { store } from "../store";
if (action.type === "SET_STEP_POSITION_INDEX") {
return update(state, {
currentGoalSteps: { $set: action.stepsArr }
});
}
/*Store.js */
import { createStore, applyMiddleware, compose, combineReducers } from "redux";
import { ApolloClient } from "react-apollo";
import { createLogger } from "redux-logger";
import { reducer as formReducer } from "redux-form";
// import { client } from './index'
import thunk from "redux-thunk";
import * as Goal_Reducer from "./Reducers/Global_Reducer";
const logger = createLogger({
collapsed: (getState, action, logEntry) => !logEntry.error,
predicate: (getState, action) => !action.type.includes("@@redux-form")
});
const client = new ApolloClient();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const store = createStore(
combineReducers({
goals: Goal_Reducer.goalReducer,
apollo: client.reducer(),
form: formReducer
}),
{}, //initial state
composeEnhancers(applyMiddleware(client.middleware(), thunk, logger))
);
哦,你只是在问为什么你必须做 store.dispatch(setStepPositionIndex());
并且仍然 dispatch()
在你的 thunk 里。因为 store.dispatch()
是使内部 returned thunk 函数使用正确参数调用的原因,而 dispatch()
ing 在 thunk 内部是将操作传播到 reducer 的原因。我可以看出这对新手来说会有多奇怪,因为 dispatch()
正在做两件不同的事情。
首先你发送 thunk,然后 thunk 发送动作。
原回答
当使用 redux-thunk
并让您的动作创建者 return 调用函数 ( return (dispatch, getState) => {
) 时,您必须手动调用 dispatch()
。您不能简单地从内部函数 return 。这就是 redux-thunk
的要点,手动控制调度。
如果您不想这样做,而不是使用 getState()
,您可以简单地使用 goals
或 currentGoalSteps
作为参数从您的组件中分派您的操作.
因为当使用 redux-thunk 时,如果 action creator returns 是一个函数而不是一个普通对象,那么该函数将被执行并且其返回值由 dispatch
函数返回。 setStepPositionIndex()
returns 函数不是普通对象,因此 store.dispatch(setStepPositionIndex())
的结果将是:
{
type: SET_STEP_POSITION_INDEX,
stepsArr: newSteps
}
其实redux-thunk
只是一个中间件,代码很简单
const thunk = store => next => action =>
typeof action === 'function'
? action(store.dispatch, store.getState)
: next(action)
您可以看到,当您传递一个函数时,中间件将执行它(使用 dispatch
和 getState
参数)和 returns 函数的值。
redux-thunk
对于在某些情况下或在延迟后调度一个动作很有用,在你的情况下我不认为你真的需要 redux-thunk
因为你是 dispatching
一个动作取决于当前状态。您可以使用 connected
组件的 mapStateToProps
来检索商店的状态
请注意,我正在用 dispatch()
呼叫 setStepPositionIndex()
。当我删除 dispatch(...)
变成 setStepPositionIndex()
我希望 setStepPositionIndex()
中的调度调用会接收它传递的普通操作对象并调度它...
或者,如果我删除 setStepPositionIndex()
中的 dispatch()
调用(并保留 dispatch(setStepPositionIndex()
),同时显式返回普通 actionObj
在其中,我希望使用 dispatch(setStepPositionIndex(actionObj))
但是成功执行此动作创建者需要两者...为什么?
/* actions.js */
import { store } from "../store.js";
store.dispatch(setStepPositionIndex());
export const SET_STEP_POSITION_INDEX = "SET_STEP_POSITION_INDEX";
export const setStepPositionIndex = () => {
return (dispatch, getState) => {
const newSteps = getState().goals.currentGoalSteps.map((stepObj, index) => {
return { ...stepObj, positionIndex: index };
});
console.log("newSteps", newSteps);
/* [{step: "Step3", positionIndex: 0}
{step: "Step2", positionIndex: 1}
{step: "Step1", positionIndex: 2}] */
const actionObj = {
type: SET_STEP_POSITION_INDEX,
stepsArr: newSteps
};
// Unsuccessful alone ->
// return actionObj
// unsuccessful alone (removing dispatch() wrapper from setStepPositionIndex
//->
return dispatch(actionObj);
};
};
/*Reducer.js*/
import * as actions from "../Actions/actions";
import { store } from "../store";
if (action.type === "SET_STEP_POSITION_INDEX") {
return update(state, {
currentGoalSteps: { $set: action.stepsArr }
});
}
/*Store.js */
import { createStore, applyMiddleware, compose, combineReducers } from "redux";
import { ApolloClient } from "react-apollo";
import { createLogger } from "redux-logger";
import { reducer as formReducer } from "redux-form";
// import { client } from './index'
import thunk from "redux-thunk";
import * as Goal_Reducer from "./Reducers/Global_Reducer";
const logger = createLogger({
collapsed: (getState, action, logEntry) => !logEntry.error,
predicate: (getState, action) => !action.type.includes("@@redux-form")
});
const client = new ApolloClient();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const store = createStore(
combineReducers({
goals: Goal_Reducer.goalReducer,
apollo: client.reducer(),
form: formReducer
}),
{}, //initial state
composeEnhancers(applyMiddleware(client.middleware(), thunk, logger))
);
哦,你只是在问为什么你必须做 store.dispatch(setStepPositionIndex());
并且仍然 dispatch()
在你的 thunk 里。因为 store.dispatch()
是使内部 returned thunk 函数使用正确参数调用的原因,而 dispatch()
ing 在 thunk 内部是将操作传播到 reducer 的原因。我可以看出这对新手来说会有多奇怪,因为 dispatch()
正在做两件不同的事情。
首先你发送 thunk,然后 thunk 发送动作。
原回答
当使用 redux-thunk
并让您的动作创建者 return 调用函数 ( return (dispatch, getState) => {
) 时,您必须手动调用 dispatch()
。您不能简单地从内部函数 return 。这就是 redux-thunk
的要点,手动控制调度。
如果您不想这样做,而不是使用 getState()
,您可以简单地使用 goals
或 currentGoalSteps
作为参数从您的组件中分派您的操作.
因为当使用 redux-thunk 时,如果 action creator returns 是一个函数而不是一个普通对象,那么该函数将被执行并且其返回值由 dispatch
函数返回。 setStepPositionIndex()
returns 函数不是普通对象,因此 store.dispatch(setStepPositionIndex())
的结果将是:
{
type: SET_STEP_POSITION_INDEX,
stepsArr: newSteps
}
其实redux-thunk
只是一个中间件,代码很简单
const thunk = store => next => action =>
typeof action === 'function'
? action(store.dispatch, store.getState)
: next(action)
您可以看到,当您传递一个函数时,中间件将执行它(使用 dispatch
和 getState
参数)和 returns 函数的值。
redux-thunk
对于在某些情况下或在延迟后调度一个动作很有用,在你的情况下我不认为你真的需要 redux-thunk
因为你是 dispatching
一个动作取决于当前状态。您可以使用 connected
组件的 mapStateToProps
来检索商店的状态