Redux Thunk - 为什么我必须两次调用dispatch()?

问题描述 投票:0回答:2

注意我用setStepPositionIndex()调用dispatch()。当我删除dispatch(...)成为setStepPositionIndex()时,我希望setStepPositionIndex()内的调度调用将接收它传递的普通操作对象并发送它......

或者,如果我在dispatch()中移除setStepPositionIndex()调用(并保持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))
);
reactjs redux redux-thunk
2个回答
6
投票

哦,你只是问为什么你必须在你的thunk里做store.dispatch(setStepPositionIndex());dispatch()。因为store.dispatch()是使用正确的参数调用内部返回的thunk函数的原因,并且thunk内部的dispatch()ing是将动作传播到reducers的内容。我可以看到这对新手来说会有多奇怪,因为dispatch()正在做两件不同的事情。

首先你派遣thunk,然后thunk调度动作。

原始答案

当使用redux-thunk并让你的动作创建者返回一个函数(return (dispatch, getState) => {)时,你必须手动调用dispatch()。你不能简单地从内部函数返回。这就是redux-thunk的意思,即手动控制调度。

如果你不想这样做,而不是使用getState(),你可以简单地从goalscurrentGoalSteps作为参数传递你的组件中的动作。


2
投票

因为当使用redux-thunk时,如果动作创建者返回一个函数而不是一个普通对象,则执行该函数并由dispatch函数返回其返回值。 setStepPositionIndex()返回的函数不是普通对象,因此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)

您可以看到,当您传递函数时,中间件将执行它(使用dispatchgetState参数)并返回函数的值。

redux-thunk对于在某些条件下或延迟后派遣行动很有用,在你的情况下,我认为你真的不需要redux-thunk,因为你是dispatching一个动作取决于当前状态。您可以使用mapStateToProps组件的connected来检索商店的状态

© www.soinside.com 2019 - 2024. All rights reserved.