在 redux-saga 中使用 call 和 put 是正确的方式
我在我的 React 应用程序中使用 redux-saga。然而,我对如何以正确的方式实现看涨期权和看跌期权效果有点困惑。
我想将新数据添加到我的 redux 状态,但是每当我使用下面列出的设置时,新的事务对象就会出现在我的 UI 中,但不会出现在 JSON 服务器中。如果我刷新页面,新添加的项目就会消失。
我的设置看起来与此完全相同的原因之一是我读到,每当分派操作时,操作都应该使用 put 效果来实现,并且这对于测试您的 Redux Saga 很有好处。
在我的情况下使用 put 效果的正确方法是什么?
我进行了以下设置:
Redux Saga
import { put, call, take, takeLatest} from "redux-saga/effects";
import {
ADD_TRANSACTION,
addTransaction
} from "state/transactions";
// POST
async function addTransactionData(payload) {
try {
const response = await fetch(`http://localhost:3010/transactions`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
const result = await response.json(payload);
return result;
} catch (error) {
throw error;
}
}
function* onAddTransactionData({ payload }) {
try {
const data = yield call(addTransactionData, payload);
yield put(addTransaction(data));
} catch (error) {
console.log(error);
}
}
export function* addTransactionWatcherSaga() {
yield take(ADD_TRANSACTION, onAddTransactionData);
}
Root Saga
import { all, call } from "redux-saga/effects";
import {
transactionsWatcherSaga,
removeTransactionWatcherSaga,
addTransactionWatcherSaga
} from "state/transactions";
export function* rootSaga() {
yield all([
call(transactionsWatcherSaga),
call(removeTransactionWatcherSaga),
call(addTransactionWatcherSaga)
]);
}
Action Creators
// ....
export const addTransaction = ({
name,
amount,
description,
isExpense
} = {}) => {
return {
type: ADD_TRANSACTION,
payload: {
id: uuidv4(),
name,
amount,
description,
isExpense
}
};
};
//...
Reducer
/* ==============================================
============== TRANSACTIONS REDUCER ============
=============================================== */
import {
ADD_TRANSACTION,
REMOVE_TRANSACTION,
EDIT_TRANSACTION,
GET_TRANSACTIONS,
SET_TRANSACTIONS
} from "state/transactions";
const initialState = {
transactions: [],
transactionsLoader: false,
error: {
message: ""
}
};
export const transactionsReducer = (state = initialState, action) => {
switch (action.type) {
// ...
case ADD_TRANSACTION:
return {
...state,
transactions: [...state.transactions, action.payload]
};
// ....
default:
return state;
}
};
我可以成功调度一个的唯一方法POST请求是这样的,但是不包括put效果。
// POST
async function addTransactionData(payload) {
try {
const response = await fetch(`http://localhost:3010/transactions`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
const result = await response.json(payload);
console.log(result);
return result;
} catch (error) {
throw error;
}
}
function* onAddTransactionData({ payload }) {
console.log(payload);
try {
yield call(addTransactionData, payload);
} catch (error) {
console.log(error);
}
}
export function* addTransactionWatcherSaga() {
yield takeLatest(ADD_TRANSACTION, onAddTransactionData);
}
I'm using redux-saga in my React application. However, I'm a bit confused of how call and put effects should be implemented in the right way.
I want to add new data to my redux state, but whenever I use the set up listed bellow, new transactions object appears in my UI, but not in the JSON Server. If I refresh the page, the newly added item disappears.
One of the reasons my set up looks exactly like this is that I read that actions should be implemented with put effect whenever dispatching an action and that it's good for testing your Redux Saga.
What is the right way to use put effect in my situation?
I have the following set up:
Redux Saga
import { put, call, take, takeLatest} from "redux-saga/effects";
import {
ADD_TRANSACTION,
addTransaction
} from "state/transactions";
// POST
async function addTransactionData(payload) {
try {
const response = await fetch(`http://localhost:3010/transactions`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
const result = await response.json(payload);
return result;
} catch (error) {
throw error;
}
}
function* onAddTransactionData({ payload }) {
try {
const data = yield call(addTransactionData, payload);
yield put(addTransaction(data));
} catch (error) {
console.log(error);
}
}
export function* addTransactionWatcherSaga() {
yield take(ADD_TRANSACTION, onAddTransactionData);
}
Root Saga
import { all, call } from "redux-saga/effects";
import {
transactionsWatcherSaga,
removeTransactionWatcherSaga,
addTransactionWatcherSaga
} from "state/transactions";
export function* rootSaga() {
yield all([
call(transactionsWatcherSaga),
call(removeTransactionWatcherSaga),
call(addTransactionWatcherSaga)
]);
}
Action creators
// ....
export const addTransaction = ({
name,
amount,
description,
isExpense
} = {}) => {
return {
type: ADD_TRANSACTION,
payload: {
id: uuidv4(),
name,
amount,
description,
isExpense
}
};
};
//...
Reducer
/* ==============================================
============== TRANSACTIONS REDUCER ============
=============================================== */
import {
ADD_TRANSACTION,
REMOVE_TRANSACTION,
EDIT_TRANSACTION,
GET_TRANSACTIONS,
SET_TRANSACTIONS
} from "state/transactions";
const initialState = {
transactions: [],
transactionsLoader: false,
error: {
message: ""
}
};
export const transactionsReducer = (state = initialState, action) => {
switch (action.type) {
// ...
case ADD_TRANSACTION:
return {
...state,
transactions: [...state.transactions, action.payload]
};
// ....
default:
return state;
}
};
The only way I can succesfully dispatch a POST request is this, but that does not include put effect.
// POST
async function addTransactionData(payload) {
try {
const response = await fetch(`http://localhost:3010/transactions`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
const result = await response.json(payload);
console.log(result);
return result;
} catch (error) {
throw error;
}
}
function* onAddTransactionData({ payload }) {
console.log(payload);
try {
yield call(addTransactionData, payload);
} catch (error) {
console.log(error);
}
}
export function* addTransactionWatcherSaga() {
yield takeLatest(ADD_TRANSACTION, onAddTransactionData);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的传奇配置不正确。每次发生
ADD_TRANSACTION
操作时,您都会为onAddTransactionData
启动一个传奇,但onAddTransactionData
最终会执行ADD_TRANSACTION
操作,因此您将循环(除非您从 API 中收到错误)。通常,您会执行诸如
ADD_TRANSACTION
之类的操作,该操作将启动传奇onAddTransactionData
。该传奇将进行 API 调用并返回结果。然后,saga 会放置一个类似LOAD_TRANSACTION_RESULTS
的操作,该操作会将 API 调用的结果包含在有效负载中,并且您的减速器将使用该结果更新您的状态。Your saga is not configured correctly. Every time a
ADD_TRANSACTION
action happens you are starting a saga foronAddTransactionData
butonAddTransactionData
ultimately puts theADD_TRANSACTION
action, so you will loop (unless you get an error from the API).Typically you'd have an action like
ADD_TRANSACTION
which would start a sagaonAddTransactionData
. That saga would make the API call and get back the result. Then the saga would put an action likeLOAD_TRANSACTION_RESULTS
that would have the result of the API call in the payload, and your reducer would update your state with that result.