Redux Thunk - Почему я должен вызывать dispatch () дважды? - PullRequest
0 голосов
/ 04 сентября 2018

Заметьте, я звоню 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 голосов
/ 04 сентября 2018

Потому что при использовании 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)

Вы можете видеть, что когда вы передаете функцию, промежуточное ПО выполняет ее (с параметрами dispatch и getState) и возвращает значение функции.

redux-thunk полезен для отправки действия при некоторых условиях или после задержки, в вашем случае я не думаю, что вам действительно нужно redux-thunk, поскольку вы dispatching действие в зависимости от текущего состояния. Вы можете использовать mapStateToProps вашего connected компонента, чтобы получить состояние магазина

0 голосов
/ 04 сентября 2018

О, вы просто спрашиваете, почему вы должны сделать store.dispatch(setStepPositionIndex()); и все же dispatch() в своем толпе. Потому что store.dispatch() - это то, что заставляет внутреннюю возвращаемую функцию thunk вызываться с правильными аргументами, а dispatch() внутри thunk - это то, что распространяет действие на редукторы. Я вижу, как это было бы странно для новичка, потому что dispatch() делает две разные вещи.

Сначала вы отправляете thunk, а thunk отправляет действие.

Оригинальный ответ

Если вы используете redux-thunk и ваш создатель действий возвращает функцию (return (dispatch, getState) => {), вы должны вручную вызвать dispatch(). Вы не можете просто вернуться из внутренней функции. Это точка redux-thunk, чтобы управлять отправкой (ями) вручную.

Если вы не хотите делать это, вместо использования getState(), вы можете просто отправить свое действие из вашего компонента с goals или currentGoalSteps, переданным в качестве аргумента.

...