UNPKG

redux-saga-watch-actions

Version:

Easily create watchers to map actions to sagas

166 lines (115 loc) 5.81 kB
# redux-saga-watch-actions Helper methods for managing sagas that respond to actions. Similar in style to [`redux-actions`](https://github.com/acdlite/redux-actions). An alternate take on [redux-loop](https://github.com/redux-loop/redux-loop). Whereas `handleActions` maps actions to reducer functions, `watchActions` maps actions to sagas. ## Installation ```bash yarn add redux-saga redux-saga-watch-actions ``` **NOTE:** [`redux-saga`](https://github.com/redux-saga/redux-saga) must be installed as a peer dependency. ## Docs - [docs](./docs) ## Example Below is a simple example of using `watchActions`. You can see that it is used to create a `rootSaga` that uses [`takeEvery`](https://redux-saga.js.org/docs/api/#takeeverypattern-saga-args) to call a saga every time a specific action is dispatched. ```js 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`](https://redux-actions.js.org/docs/api/handleAction.html#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. ```js 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](https://github.com/redux-saga/redux-saga#sagasjs). We've used `watchActions` to create the `takeEvery` rootSaga ```js 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`](https://redux-saga.github.io/redux-saga/docs/api/index.html#takeeverypattern-saga-args) 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. ```js 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`](https://redux-actions.js.org/docs/api/handleAction.html#handleactions) from redux-actions. Whereas `handleActions` maps actions to reducer functions, `watchActions` maps actions to sagas. ```js 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)` ```js import { watchActions } from 'redux-saga-watch-actions' ``` This creates a `rootSaga` from the `sagaMap` which will use [`takeEvery`](https://redux-saga.github.io/redux-saga/docs/api/index.html#takeeverypattern-saga-args) to map actions to sagas. Internally, this calls `createWatcher()` to create a saga for each action type. ```js 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)` ```js 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](https://github.com/redux-saga/redux-saga#sagasjs). ```js 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](./docs/middleware/README.md).