如何在Redux-Saga中实现回调?

时间:2016-12-10 14:24:58

标签: reactjs redux redux-saga

方案是,我想在调度操作后根据成功,错误回调重定向用户或显示警报。

以下是使用 redux-thunk 执行任务的代码

this.props.actions.login(credentials)
.then((success)=>redirectToHomePage)
.catch((error)=>alertError);

因为redux-thunk中的调度操作返回Promise,所以很容易对响应采取行动。

但是现在我在redux-saga上弄脏了,试图弄清楚如何能够获得与上面代码相​​同的结果。由于Saga在不同的线程上运行,我无法从上面的查询中获得回调。所以我只想知道你们是怎么做到的。或者什么是使用redux-saga时处理回调的最佳方法? 调度操作如下所示:

  

this.props.actions.login(凭证);

和传奇

function* login(action) {
  try {
    const state = yield select();
    const token = state.authReducer.token;
    const response = yield call(API.login,action.params,token);
    yield put({type: ACTION_TYPES.LOGIN_SUCCESS, payload:response.data});
    yield call(setItem,AUTH_STORAGE_KEY,response.data.api_token);
  } catch (error) {
    yield put({type: ACTION_TYPES.LOGIN_FAILURE, error})
  }
}

传奇监视器

export function* loginMonitor() {
  yield takeLatest(ACTION_TYPES.LOGIN_REQUEST,login);
}

动作创作者

function login(params) {
  return {
    type: ACTION_TYPES.LOGIN_REQUEST,
    params
  }
}

5 个答案:

答案 0 :(得分:8)

我花了一整天的时间来研究这些东西,从thunk切换到redux-saga

我也有很多看起来像这样的代码

this.props.actions.login(credentials)
.then((success)=>redirectToHomePage)
.catch((error)=>alertError);

可以使用thunk + saga

function login(params) {
  return (dispatch) => {
    return new Promise((resolve, reject) => {
      dispatch({
        type: ACTION_TYPES.LOGIN_REQUEST,
        params,
        resolve, 
        reject
      })
    }
  }
}

然后在saga land中你可以做类似的事情

function* login(action) {
  let response = yourApi.request('http://www.urthing.com/login')
  if (response.success) {
    action.resolve(response.success) // or whatever
  } else { action.reject() }
}

答案 1 :(得分:6)

我认为您应该向登录生成器添加重定向和警报。这样所有逻辑都在传奇中,它仍然很容易测试。所以基本上你的登录传奇看起来像这样:

function* login(action) {
  try {
    const state = yield select();
    const token = state.authReducer.token;
    const response = yield call(API.login,action.params,token);
    yield put({type: ACTION_TYPES.LOGIN_SUCCESS, payload:response.data});
    yield call(setItem,AUTH_STORAGE_KEY,response.data.api_token);
    yield call(redirectToHomePage); // add this...
  } catch (error) {
    yield put({type: ACTION_TYPES.LOGIN_FAILURE, error});
    yield call(alertError); // and this
  }
}

答案 2 :(得分:0)

您可以简单地通过将有关成功和错误回调函数的额外信息传递到有效负载本身来进行工作。因此,redux模式以一种完全分离的方式工作。

this.props.actions.login({
   credentials,
   successCb: success => redirectToHomePage)
   errorCb: error => alertError)
 });

在传奇中,您可以从有效载荷中解构这些回调,并根据程序流非常轻松地运行它们。

答案 3 :(得分:0)

您的通话:

this.props.addCutCallback(currentTime, callback);

您传递给 connect()函数的映射:

const mapDispatchToProps = (dispatch) => ({
  addCutCallback: (time, callback) =>
    dispatch(ACTIONS.addCutCallback(time, callback)),
});

export default connect(mapStateToProps, mapDispatchToProps)(Home);

你的传奇:

import {put, takeEvery, all, select} from 'redux-saga/effects';
import * as Actions from './../actions';

const getCuts = (state) => state.cuts;

function* addCutSaga({time, callback}) {
  yield put({type: Actions.ADD_CUT, time});
  const cuts = yield select(getCuts);
  callback(cuts);
}

function* cutsSaga() {
  yield takeEvery(Actions.ADD_CUT_CALLBACK, addCutSaga);
}

export default function* rootSaga() {
  yield all([cutsSaga()]);
}

答案 4 :(得分:0)

我觉得更优雅的一种方法是简单地使用 useEffect

//selectors.ts

export function hasAuthError(state: RootState): boolean {
  return state.auth.error;
}

export function getAuthMessage(state: RootState): string {
  return state.auth.message;
}
// some react component

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import Toast from 'react-native-toast-message';
import { getAuthMessage, hasAuthError } from 'src/store/auth/selectors';

  ...

  const message = useSelector(getAuthMessage);
  const hasError = useSelector(hasAuthError)

  ...

  useEffect(() => {
    if (hasError) {
      Toast.show({
        type: 'error',
        text2: message,
        topOffset: 50,
        visibilityTime: 5000
      });
    }
  }, [message, hasError]);