redux-saga-watch-actions

Easily create watchers to map actions to sagas

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
redux-saga-watch-actions
0.3.0-05 years ago7 years agoMinified + gzip package size for redux-saga-watch-actions in KB

Readme

redux-saga-watch-actions
Helper methods for managing sagas that respond to actions. Similar in style to redux-actions. An alternate take on redux-loop.
Whereas handleActions maps actions to reducer functions, watchActions maps actions to sagas.

Installation

yarn add redux-saga redux-saga-watch-actions

NOTE: redux-saga must be installed as a peer dependency.

Docs

Example

Below is a simple example of using watchActions. You can see that it is used to create a rootSaga that uses takeEvery to call a saga every time a specific action is dispatched.
import { watchActions } from 'redux-saga-watch-actions'
import { INCREMENT, DECREMENT } from './constants'
import { increment, decrement } from './sagas'

const rootSaga = watchActions({
  [INCREMENT]: increment,
  [DECREMENT]: decrement,
})
export default rootSaga

Comparison to handleActions

Below you can see a reducer being created with handleActions. Reducers and saga do very different things, however, they are similar in that a reducer function expects to be called whenever a specific action is dispatched.
import { handleActions } from 'redux-actions'
import { INCREMENT, DECREMENT } from './constants'
import { increment, decrement } from './reducers'

const reducer = handleActions({
  [INCREMENT]: increment,
  [DECREMENT]: decrement,
})
export default reducer

Rewritten example from redux-saga

The example below closely matches the fetchUser example in the redux-saga readme. We've used watchActions to create the takeEvery rootSaga
import { watchActions } from 'redux-saga-watch-actions'
import { call, put } from 'redux-saga/effects'
import Api from '...'

// worker Saga: will be fired on USER_FETCH_REQUESTED actions
const fetchUser = function*(action) {
  try {
    const user = yield call(Api.fetchUser, action.payload.userId)
    yield put({ type: 'USER_FETCH_SUCCEEDED', user: user })
  } catch (e) {
    yield put({ type: 'USER_FETCH_FAILED', message: e.message })
  }
}

const mySaga = watchActions({
  ['USER_FETCH_REQUESTED']: fetchUser,
})

export default mySaga

What does watchActions do?

It's a convenience method that removes the boilerplate of having to use takeEvery to hook your saga up to actions.

Example: without watchActions

It's illuminating to see an example without using watchActions. Below you can see the basics of what watchActions does using vanilla redux-saga boilerplate. We are creating a rootSaga that will capture certain dispatched actions and feed them into a generator function. If you've used redux-saga, you've probably done something similar before.
import { all, takeEvery } from 'redux-saga/effects'

import { runSaga } from './store/sagas'

// grab action constants and sagas from your app
import { INCREMENT, DECREMENT } from './constants'
import { increment, decrement } from './sagas'

// without watch actions
const rootSaga = function*() {
  yield all([takeEvery(INCREMENT, increment), takeEvery(DECREMENT, decrement)])
}

runSaga(rootSaga)

Example: with watchActions

How does watchActions make things easier? It doesn't, really. The watchActions function is a convenience method. It allows you to quickly create a root saga that marries actions to sagas, similar to how redux marries actions to reducers. The benefit is conceptual parity with handleActions from redux-actions. Whereas handleActions maps actions to reducer functions, watchActions maps actions to sagas.
import { watchActions } from 'redux-saga-watch-actions'

import { runSaga } from './store/sagas'

// grab action constants and sagas from your app
import { INCREMENT, DECREMENT } from './constants'
import { increment, decrement } from './sagas'

// with watch actions
const rootSaga = watchActions({
  [INCREMENT]: increment,
  [DECREMENT]: decrement,
})

runSaga(rootSaga)

Usage

watchActions(sagaMap)

import { watchActions } from 'redux-saga-watch-actions'

This creates a rootSaga from the sagaMap which will use takeEvery to map actions to sagas. Internally, this calls createWatcher() to create a saga for each action type.
import { watchActions } from 'redux-saga-watch-actions'
import { INCREMENT, DECREMENT } from './constants'
import { increment, decrement } from './sagas'

const rootSaga = watchActions({
  [INCREMENT]: increment,
  [DECREMENT]: decrement,
})
export default rootSaga

createWatcher(actionType, saga)

import { createWatcher } from 'redux-saga-watch-actions'

You don't normally need to call createWatcher yourself. Used internally by watchActions. Returns a generator function that uses takeEvery(actionType, saga) to respond to dispatched actions. Compare to mySaga in the redux-saga usage example.
import { createWatcher } from 'redux-saga-watch-actions'
import { INCREMENT } from './constants'
import { increment } from './sagas'

const mySaga = createWatcher(INCREMENT, increment)
export default mySaga

Middleware

You might want to read about the included middleware.