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

时间:2018-09-03 22:23:29

标签: reactjs redux redux-thunk

请注意,我正在用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))
);

2 个答案:

答案 0 :(得分:6)

哦,您只是在问为什么必须要做#include "Map.h" #include <iostream> #include <fstream> #include <cstdlib> void Map::loadLevel() { ifstream load; load.open("SaveInfo.txt"); if (load.fail()) { perror("SaveInfo.txt"); } getline(load, _levelNumber); load.close(); //Opens level file load.open(_levelNumber); if (load.fail()) { perror(_levelNumber.c_str()); } load >> _levelSize; for (int y = 0; y < _levelSize; y++) { getline(load, _levelLineBuffer); _level.push_back(_levelLineBuffer); } load.close(); } void Map::printLevel() { for (int y = 1; y < _levelSize; y++) { cout << _level[y] << endl; } } 而仍然store.dispatch(setStepPositionIndex());在您的重击中。因为dispatch()是使内部返回的thunk函数被正确的参数调用的原因,而store.dispatch()则是在thunk内部将动作传播到减速器的原因。我可以看到这对于新来者来说很奇怪,因为dispatch()在做两件事。

首先,您派遣thunk,然后thunk派遣动作。

原始答案

使用dispatch()并让操作创建者返回函数(redux-thunk)时,必须手动调用return (dispatch, getState) => {。您不能简单地从内部函数返回。这就是dispatch()的关键,可以手动控制调度。

如果您不想执行此操作,则可以使用redux-thunkgetState()作为参数传递,而不用使用goals,而只需从组件中分派操作。 / p>

答案 1 :(得分:2)

因为使用redux-thunk时,如果动作创建者返回一个函数而不是一个普通对象,则该函数将执行,其返回值由if (Notification.permission === "granted") { // Push notification permission granted. } 函数返回。 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) dispatch参数)并返回函数的值。

getState对于在某些情况下或延迟后分派操作很有用,在您的情况下,我认为您确实不需要redux-thunk,因为您redux-thunk取决于当前状态。您可以使用dispatching组件中的mapStateToProps来检索商店的状态