Skip to content

simpleAsync

Peter Gundel edited this page Jul 7, 2017 · 3 revisions

Source

Warning: The simpleAsync feature is currently under consideration and we expect heavy (breaking) API changes.

Side-effects with redux-saga

Using the redux-belt generated actions, you can write sagas that make use of the meta object:

import { types } from './actions'
import { requestAddBook } from './api'

function* asyncAddBook(action) {
  try {
    const response = yield call(requestAddBook, action.payload)
    yield put({ type: action.meta.success, payload: response.data })
  } catch (error) {
    yield put({ type: action.meta.failure, payload: error })
  }
}

function* booksSaga() {
  yield takeEvery(types.ADD_BOOK, asyncAddBook)
}

A frequent use case for a saga is to wrap Redux actions around a network request, or an impure function, or whatever it is that takes time to complete. In the simplest (and most common) scenario, a saga tries to perform a task. If it succeeds, it dispatches a success action. If it fails, it dispatches a failure action. For all these use cases, redux-belt provides the simpleAsync function, which works with redux-belt generated actions:

import { simpleAsync } from 'redux-belt'

// This does exactly the same as the example saga above
const asyncAddBook = simpleAsync({ effect: requestAddBook })

function* booksSaga() {
  yield takeEvery(types.ADD_BOOK, asyncAddBook)
}

/**
 * Now, calling addBook with an argument like this:
 * addBook({ id: 1, title: 'The Stranger', author: 'Albert Camus' })
 *
 * Will trigger asyncAddBook, which will call requestAddBook with exactly the same payload:
 * { id: 1, title: 'The Stranger', author: 'Albert Camus' }
 */

In a more complicated scenario, a saga could call yet another set of actions on success. You can do this with simpleAsync by providing a function to the afterSuccess key. The function provided to afterSuccess will be called with two arguments: the original payload passed to the action and the response from the effect. You can choose to pass whichever you want, in this case we're passing the response:

import { simpleAsync } from 'redux-belt'

const asyncAddBook = simpleAsync({
  effect: requestAddBook,
  afterSuccess: (payload, response) => addBookSuggestions(response)
})

function* booksSaga() {
  yield takeEvery(types.ADD_BOOK, asyncAddBook)
}

In a reducer, you can react to the actions dispatched by these sagas like so:

import { types } from './actions'

function booksReducer(state = {}, action) {
  switch (action.type) {
    case types.ADD_BOOK:
      // Do something
    case types.ADD_BOOK_SUCCESS:
      // Do something
    case types.ADD_BOOK_FAILURE:
      // Do something
    default:
      return state
  }
}