Skip to content

Latest commit

 

History

History
70 lines (54 loc) · 2.42 KB

DispatchingActions.md

File metadata and controls

70 lines (54 loc) · 2.42 KB

Dispatching actions to the store

Taking the previous example further, let's say that after each save, we want to dispatch some action to notify the Store that the fetch has succeeded (we'll omit the failure case for the moment).

We could pass the Store's dispatch function to the Generator. Then the Generator could invoke it after receiving the fetch response:

// ...

function* fetchProducts(dispatch) {
  const products = yield call(Api.fetch, '/products')
  dispatch({ type: 'PRODUCTS_RECEIVED', products })
}

However, this solution has the same drawbacks as invoking functions directly from inside the Generator (as discussed in the previous section). If we want to test that fetchProducts performs the dispatch after receiving the AJAX response, we'll need again to mock the dispatch function.

Instead, we need the same declarative solution. Just create an Object to instruct the middleware that we need to dispatch some action, and let the middleware perform the real dispatch. This way we can test the Generator's dispatch in the same way: by just inspecting the yielded Effect and making sure it contains the correct instructions.

The library provides, for this purpose, another function put which creates the dispatch Effect.

import { call, put } from 'redux-saga/effects'
// ...

function* fetchProducts() {
  const products = yield call(Api.fetch, '/products')
  // create and yield a dispatch Effect
  yield put({ type: 'PRODUCTS_RECEIVED', products })
}

Now, we can test the Generator easily as in the previous section

import { call, put } from 'redux-saga/effects'
import Api from '...'

const iterator = fetchProducts()

// expects a call instruction
assert.deepEqual(
  iterator.next().value,
  call(Api.fetch, '/products'),
  "fetchProducts should yield an Effect call(Api.fetch, './products')"
)

// create a fake response
const products = {}

// expects a dispatch instruction
assert.deepEqual(
  iterator.next(products).value,
  put({ type: 'PRODUCTS_RECEIVED', products }),
  "fetchProducts should yield an Effect put({ type: 'PRODUCTS_RECEIVED', products })"
)

Note how we pass the fake response to the Generator via its next method. Outside the middleware environment, we have total control over the Generator, we can simulate a real environment by simply mocking results and resuming the Generator with them. Mocking data is a lot simpler than mocking functions and spying calls.