reducer 中未定义的 React-Redux-Saga 动作负载

React-Redux-Saga action payload undefined in reducer

我正在尝试创建一个基本的计数器应用程序。 但是在我的减速器中,我似乎无法调用 action.payload.step(该步骤将来自我的操作,它应该代表在调度时传入的值。

确认一下,我想在我的减速器中添加步骤,因为我不应该调用 + 1 我应该传递步骤值。

减速器:

import {
  INCREMENT_REQUEST,
  INCREMENT_SUCCESS,
  INCREMENT_FAILURE,
  DECREMENT_REQUEST,
  DECREMENT_SUCCESS,
  DECREMENT_FAILURE,
} from "../actions/actionTypes";

const initialState = {
  value: 0,
  loading: null,
  error: null,
};

const counterReducers = (state = initialState, action) => {
  switch (action.type) {
    case INCREMENT_REQUEST:
      return { ...state, loading: true, error: null };
    case INCREMENT_SUCCESS:
      return {
        ...state,
        value: state.value + 1,
        loading: false,
        error: null,
      };
    case INCREMENT_FAILURE:
      return { ...state, error: action.error };
    case DECREMENT_REQUEST:
      return { ...state, loading: true, error: null };
    case DECREMENT_SUCCESS:
      return {
        ...state,
        value: state.value - 1,
        loading: false,
        error: null,
      };
    case DECREMENT_FAILURE:
      return { ...state, error: action.error };

    default:
      return state;
  }
};

export default counterReducers;

操作:

import { INCREMENT_REQUEST, DECREMENT_REQUEST } from "./actionTypes";

export const incrementAction = (step) => {
  return {
    type: INCREMENT_REQUEST,
    payload: {
      step: step,
    },
  };
};

export const decrementAction = (step) => {
  return {
    type: DECREMENT_REQUEST,
    payload: {
      step: step,
    },
  };
};

容器:

import { useSelector, useDispatch } from "react-redux";
import CounterComponent from "../components/CounterComponent";

const CounterContainer = () => {
  const counter = useSelector((state) => state.counterReducers);

  const dispatch = useDispatch();

  return <CounterComponent counter={counter} dispatch={dispatch} />;
};

export default CounterContainer;

UI Component/Child 分量:

import React from "react";
import { decrementAction, incrementAction } from "../actions";

const CounterComponent = ({ counter, dispatch }) => {
  return (
    <div>
      <h1>Counter - Redux Saga Flow Example</h1>
      <button onClick={() => dispatch(incrementAction(1))}>
        Increment + 1
      </button>
      <button onClick={() => dispatch(decrementAction(1))}>
        Decrement - 1
      </button>
      {counter.loading ? <div>loading</div> : <div>Count: {counter.value}</div>}
    </div>
  );
};

export default CounterComponent;

传奇:

import { takeEvery, call, put } from "redux-saga/effects";

const delay = (ms) => new Promise((res) => setTimeout(res, ms));

function* incrementAsync() {
  yield call(delay, 2000);
  yield put({ type: "INCREMENT_SUCCESS" });
}

export function* watchIncrement() {
  yield takeEvery("INCREMENT_REQUEST", incrementAsync);
}

function* decrementAsync() {
  yield call(delay, 2000);
  yield put({ type: "DECREMENT_SUCCESS" });
}

export function* watchDecrement() {
  yield takeEvery("DECREMENT_REQUEST", decrementAsync);
}

如有任何帮助,我们将不胜感激!

2021 年 9 月 15 日更新

嘿时髦,在你发表评论后我检查了你的代码,缺少的部分正在将有效负载从“_REQUEST”传递到“_SUCCESS”操作,

当您执行 yield put({ type: "INCREMENT_SUCCESS" }) 时,这里没有“有效载荷”对象,只是 action.type 在您的减速器中,

takeEvery使用的函数会收到redux派发的原始action对象,你只需要转发给最终的action,

喜欢以下内容:

function* incrementAsync(action) {
  yield call(delay, 2000);
  yield put({ type: "INCREMENT_SUCCESS", payload: action.payload });
}

export function* watchIncrement() {
  yield takeEvery("INCREMENT_REQUEST", incrementAsync);
}

function* decrementAsync(action) {
  yield call(delay, 2000);
  yield put({ type: "DECREMENT_SUCCESS", payload: action.payload });
}

export function* watchDecrement() {
  yield takeEvery("DECREMENT_REQUEST", decrementAsync);
}

我还更新了codesandbox示例: https://codesandbox.io/s/redux-saga-counter-async-wsep6

==========原答案

你有没有将你的 sagas 初始化为中间件?

对于你的故事,类似于:

export default function* rootSaga() {
  yield all([
    watchIncrement(),
    watchDecrement()
  ])
}

和你的商店,像这样:

const sagaMiddleware = createSagaMiddleware()
const store = ...
sagaMiddleware.run(rootSaga)

如果你不启动它们,它们将不会监听商店中的事件并触发它们的动作

我用你的例子创建了一个 CodeSandbox 并添加了“rootSaga”,看起来工作正常:

https://codesandbox.io/s/redux-saga-counter-async-wsep6

可以在以下位置找到关于它的演练:https://redux-saga.js.org/docs/introduction/BeginnerTutorial