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
我正在尝试创建一个基本的计数器应用程序。
但是在我的减速器中,我似乎无法调用 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