处理 Redux Saga 结果以查看源自哪个动作调用

IT技术 reactjs promise redux react-redux redux-saga
2021-05-19 19:40:31

我是 Redux Saga 的新手,来自 Redux Thunk。在某些情况下,我需要从调用操作的视图内部了解 API 调用是失败还是成功。使用 Redux Thunk,我将执行以下操作。

我的组件和动作创建者看起来像这样:

class MyComponent extends Component {

  componentDidMount() {
    this.props.actions.fetchItems()
    .then(result => {
        if (result.status === 'OK') {
            console.log('Request succeeded, take particular action in this view')
        }
        else {
            console.log('Request failed, take other action in this view')
        }
    })
  }

  render() {
    return (
        <div>My view</div>
    )
  }
}


const mapStateToProps = (state, ownProps) => {
    return {
        items: state.items,
    }
}

const mapDispatchToProps = dispatch => {
    return {
        actions: bindActionCreators({
            ...actions,
        }, dispatch),
    }
}


export default connect(
    mapStateToProps,
    mapDispatchToProps,
)(MyComponent)



import * as t from './actionTypes'
import {CALL_API} from '../api'

const xhrGetItems = (params) => (dispatch, getState) => {
    const action = {
        [CALL_API]: {
            type: t.XHR_ITEMS_FETCH,
            endpoint: `http://www.example.com/myendpoint`,
            method: 'get',
        }
    }
    return dispatch(action)
}

我的 API 中间件使用一个CALL_API属性捕获所有操作,使用 ajax 库进行适当的调用,然后返回一个已履行的Promise。我的减速器设置为处理 api 调用的每个可能状态(成功、失败、挂起)。一直以来,我仍然可以在我的视图中检查调用的结果。

所以我的问题是,如何使用 Redux Saga 实现这一点?现在我的 saga api 中间件正在做它应该做的一切,但是当我fetchItems()在视图中调用时,结果是一个普通的 JS 对象,所以我无法检查它是否成功。

我也有可能完全错了。非常感谢任何建议。

1个回答

redux 和 redux-saga 的常见模式是为 API 调用创建 3 个操作。在你的情况下,我会创建:

  • LIST_ITEMS_START
  • LIST_ITEMS_SUCCEEDED
  • LIST_ITEMS_FAILED

你的传奇看起来像这样:

function* watchListItemsStart() {
  yield takeLatest(LIST_ITEMS_START, listItemsStartFlow)
}

function* listItemsStartFlow() {
  try {
    const result = yield call(api.getItems)

    if (result.status === 'OK') {
      yield put(LIST_ITEMS_SUCCEEDED, items)
    } else {
      throw new Error(result.error)
    }
  } catch (error) {
    yield put(LIST_ITEMS_FAILED, error)
  }
}

传奇已经干净地抽象出了 API 副作用。reducer 可以专注于状态管理:

switch (action.type) {
  case LIST_ITEMS_START:
    return {
      ...state,
      isLoading: true,
      error: null,
      items: [],
    }
  case LIST_ITEMS_SUCCEEDED:
    return {
      ...state,
      isLoading: false,
      items: action.payload.items,
    }
  case LIST_ITEMS_FAILED:
    return {
      ...state,
      isLoading: false,
      error: action.payload.error.getMessage(),
    }
}

现在,您在商店中拥有了可以在组件中进行选择和react的所有内容。

class MyComponent extends Component {
  componentDidMount() {
    this.props.fetchItems()
  }

  render() {
    const { isLoading, items, error } = this.props

    // Here you can react to the different states.

    return (
      <div>My view</div>
    )
  }
}

connect(state => ({
  isLoading: itemsSelectors.isLoading(state),
  items: itemsSelectors.getItems(state),
  error: itemsSelectors.getError(state),
}), {
  fetchItems: actions.fetchItems
})(MyComponent)

这里重要的一点是,您的组件变得非常愚蠢。它只是获取 props 而不会处理 API 调用的结果(promise.then这里没有)。

我希望这个答案能帮到你。