Handling Redux Saga result in view from which action call originates

喜你入骨 提交于 2021-02-09 10:57:15

问题


I'm new to Redux Saga, coming from Redux Thunk. In some situations, I need to know whether an API call fails or succeeds from inside the view from which I called the action. With Redux Thunk, I would do something like the following.

My component and action creator would look like this:

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)
}

My API middleware catches all actions with a CALL_API property, uses an ajax library to make the appropriate call, then returns a fulfilled promise. My reducer is set up to handle each of the possible states of the api call (success, failure, pending). All the while, I can still check the result of the call in my view where it originated.

So my question is, how can this be accomplished with Redux Saga? Right now my saga api middleware is doing everything it should be doing, but when I call fetchItems() in my view, the result is a plain JS object, so I can't check whether or not it succeeded.

It's possible that I'm going about this completely wrong, too. Any suggestions are very much appreciated.


回答1:


A common pattern with redux and redux-saga is to create 3 Actions for an API call. In your case I would create:

  • LIST_ITEMS_START
  • LIST_ITEMS_SUCCEEDED
  • LIST_ITEMS_FAILED

Your saga would look something like this:

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)
  }
}

The sagas have cleanly abstracted away the API side-effect. The reducer can concentrate on state management:

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(),
    }
}

Now you have everything you need in your store that can be selected and reacted on in the component.

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)

An important point here is, that your component gets very dumb. It just gets props and does not handle the result of the API call (no promise.then here).

I hope this answer will help you.



来源:https://stackoverflow.com/questions/43991460/handling-redux-saga-result-in-view-from-which-action-call-originates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!