与Redux Saga反应-如何从axios调用中获取数据



我正在使用React+Redux+Saga,到目前为止我所做的一切都很完美,但我需要在(成功调用(后发回数据。

调度到路由=>发送回ID=>获取ID

但它做不到。

路线(快递服务器(:

axios.post( ... 
return res.json(resAlbum);

我的传奇:

function* postSpotifyAlbum(obj) {
obj = {
method: "POST",
url: BASEurl,
params: {
token: obj.payload.token,
albumCode: obj.payload.albumCode,
albumGenres: obj.payload.albumGenres,
userCode: obj.payload.userCode,
},
};

try {
const spotifyCategories = yield call(axios, axiosCall(obj));
yield put({
type: "POST_SPOTIFY_ALBUMS_SUCCESS",
payload: JSON.parse(spotifyCategories.data),
});
return spotifyCategories.data;
} catch (error) {
console.log(error);
yield put({ type: "POST_SPOTIFY_ALBUMS_ERROR", payload: error });
}
} 

组件:

const res = await dispatch(postSpotifyAlbums(obj));

如果我控制台记录res,我只会得到我刚刚发送的Obj。

问题:

有没有办法从SAGA寄回一些东西

即res给我刚插入的obj

或者没有办法,那么我需要再次调用reducer,把刚刚插入的obj还给我

我重复一遍,从发货到减速器,一切都很完美(我承诺更短(我只是想看看我是否可以扩展我的SAGA知识

使用Saga

调用dispatch返回的值只是您调度的操作。你的传奇故事将";取";此操作和分派其他操作,但这都被认为是独立的。因此,您的res变量就是原始动作postSpotifyAlbums(obj)

或者没有办法,那么我需要对reducer进行第二次调用,把刚刚插入的obj还给我?

是的,您需要在侦听发布值的组件中有一个useSelector


伴有雷声

使用redux-thunk更容易做到这一点,因为thunk中间件覆盖了dispatch的默认行为。当你调度一个thunk(一个动作创建者,它是dispatch的函数(时,你会得到thunk返回的值。

内部函数的任何返回值都可以作为dispatch本身的返回值。这对于协调异步控制流非常方便,thunk操作创建者相互调度并返回Promises以等待对方的完成-docs

动作

const postSpotifyAlbums = (payload) => async (dispatch) => {
dispatch({ type: "POST_SPOTIFY_ALBUMS_PENDING" });
const args = {
method: "POST",
url: BASEurl,
params: {
token: payload.token,
albumCode: payload.albumCode,
albumGenres: payload.albumGenres,
userCode: payload.userCode
}
};
try {
const spotifyCategories = await axios.request(args);
dispatch({
type: "POST_SPOTIFY_ALBUMS_SUCCESS",
payload: spotifyCategories.data
});
// we can customize the returned value here to anything!
return spotifyCategories.data;
} catch (error) {
console.log(error);
dispatch({ type: "POST_SPOTIFY_ALBUMS_ERROR", payload: error });
}
};

组件

const doDispatch = async () => {
// we get back whatever we specifically returned in the thunk
const data = await dispatch(postSpotifyAlbums(obj));
console.log("result", data);
// we didn't return anything in the error case so it would be undefined
if (data) {
// do something with success
}
};

使用createAsyncThunk

redux工具箱包括一个助手函数createAsyncThunk;挂起"被拒绝";以及";满足";一步到位。这里的返回值是调度的最后一个操作。

当调度时,thunk将。。。返回包含最终调度操作(fulfilledrejected操作对象(的已完成承诺-docs

动作

const postSpotifyAlbums = createAsyncThunk(
"POST_SPOTIFY_ALBUMS",
async (payload) => {
const args = {
method: "POST",
url: BASEurl,
params: {
token: payload.token,
albumCode: payload.albumCode,
albumGenres: payload.albumGenres,
userCode: payload.userCode
}
};
const spotifyCategories = await axios.request(args);
return spotifyCategories.data;
}
);

组件

const doDispatch = async () => {
const action = await dispatch(postSpotifyAlbums(obj));
console.log("result", action);
// we could have the success or the failure action
if ( action.type === postSpotifyAlbums.fulfilled.type) {
// do something with success
const data = action.payload;
} else {
// do something with error
const error = action.error;
}
};

不确定您是否仍在寻找解决方案,但这是我的代码实现。流量是这样的。

  1. 我们从组件发出调度请求
  2. redux调度称为";INITIATE_TRANACTION">
  3. redux-saga拦截了该操作,并在此基础上开始进行api调用
  4. API调用成功;INITIATE_TRANACTION_SUCCESS";随api的值一起调度
  5. 现在,Saga将axios的值返回到实际调用函数,从该函数调用步骤1调度

这是代码。

// store.js
import {middleware as thunkMiddleware} from 'redux-saga-thunk';
const middlewares = [thunkMiddleware];
const sagaMiddleware = createSagaMiddleware();
middlewares.push(sagaMiddleware);
if (process.env.NODE_ENV === `development`) {
const {logger} = require(`redux-logger`);
middlewares.push(logger);
}
const persistConfig = {
key: 'root',
storage: AsyncStorage,
white: ['errors'],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: middlewares,
devTools: process.env.NODE_ENV === `development` ? true : false,
});
// Payment.js(or any of your component)
const handleBtnClick = async (type, value) => {
console.log('btn click type', type, route.params, value);
switch (type) {
case 'pay':
try {
let orderId = 'OD_' + moment().format('YYYYMMDDHHmmss');
// Here we are dispatching action "INITIATE_TRANSACTION" to redux saga.
// Step 1.
const response = await props.initiatePayment({
orderId,
orderAmount: 10,
orderCurrency: 'INR',
});
console.log('response', response.data.cftoken);
}catch (error){
console.log('error', error)
}
break;
}
// Middleware used is redux-saga-thunk, which basically implements functionality of thunk in redux saga. so meta: {thunk: true} waits for the whole execution to finish and then continues.
// Step 2
export const initiatePayment = data => ({
type: INITIATE_TRANSACTION,
data,
meta: {thunk: true},
});
//Step 3
// Here post is just a custom function for api call, onError and onSuccess are the handler functions and safe is the wrapper method which basically implements try catch logic and handles errors for us without repeating much of the code.
// paymentSaga.js
function* initiateTransactionSaga({data, meta}) {
const response = yield call(post, API.INITIATE_TRANSACTION, data);
return response; //Step 4....
}
export default function* paymentSaga() {
yield takeLatest(
INITIATE_TRANSACTION,
safe(onError, initiateTransactionSaga, onSuccess), //onSuccess required if you want values to be returned to step 1
);
}
// axiosApi.js
export async function post(url, data, config = {}) {
console.log('url data config', url, data, config);
return axiosApi
.post(url, {...data}, {...config})
.then(response => response.data);
}
// Sagahelper.js

/**
* @param handler --- Error handler function. In our case, onError Function
* @param saga --- Actual Saga function. in our case Api is called and data is returned
* @param success --- success redux action dispatch function -- in our case, if we need to pass response coming from api to the actual calling function( something like props.viewingItem(data)), then pass it here, otherwise leave it blank
* @
*/
export const safe = (
handler: any = null,
saga: any,
success: any = null,
...args: any
) =>
function* (action: any) {
try {
console.log('action in safe===', action, success);
const res1 = yield call(saga, ...args, action);
// Success wrapper. if you pass onSuccess method, then only this part will be executed. If you do not want the values to be returned from redux-saga to your component function call, then i suggest you skip it.
if (success) {
yield call(success, res1, action.type, action.meta);
return res1; //This line returns value to the component function( to step 1)
}
} catch (err) {
yield call(handler, ...args, err, action.type, action.meta);
}
};
export function* onError(err: any, type: any, meta: any) {
console.log('type onError', type);
yield put({
type: type + '_ERROR',
payload: err,
error: true,
meta,
});

// Do something with the error msg. like show alert, etc...
return err;
}
export function* onSuccess(response: any, type: any, meta: any) {
console.log('type onError', response);
yield put({
type: type + '_SUCCESS',
payload: response,
error: false,
meta,
});
// Do something with the success msg. like show alert, etc...
return response;
}

你可以在这里找到详细信息。https://medium.com/@dhavaljavia.p/redux-saga-return-values-from-saga-to-our-component-using-redux-saga-shunk-17ad6e9e81ef

相关内容

  • 没有找到相关文章

最新更新