アクションをストアにディスパッチする
前の例をさらに進めましょう。保存のたびに、フェッチが成功したことをストアに通知するアクションをディスパッチしたいとします(ここでは失敗ケースは省略します)。
ジェネレーターにストアのdispatch関数を渡すことができます。すると、ジェネレーターはフェッチレスポンスを受信した後にこれを呼び出すことができます
// ...
function* fetchProducts(dispatch) {
const products = yield call(Api.fetch, '/products')
dispatch({ type: 'PRODUCTS_RECEIVED', products })
}
ただし、このソリューションには、ジェネレーター内から関数を直接呼び出す場合と同じ欠点があります(前のセクションで説明したとおり)。fetchProductsが AJAX レスポンスを受信した後にディスパッチを実行するかをテストする場合は、もう一度dispatch関数をモックする必要があります。
代わりに、同じ宣言型ソリューションが必要です。ミドルウェアに対して、アクションをディスパッチする必要があることを指示するプレーンな JavaScript オブジェクトを作成し、ミドルウェアが実際のディスパッチを実行できるようにします。このようにすると、生成されたエフェクトを調べてそれが正しい命令を含んでいることを確認することで、ジェネレーターのディスパッチを同じ方法でテストできます。
この目的のために、ライブラリはディスパッチエフェクトを作成する別の関数putを提供しています。
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 })
}
これで、前のセクションのようにジェネレーターを簡単にテストできます
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 })"
)
nextメソッドを介してジェネレーターに偽のレスポンスを渡す方法に注意してください。ミドルウェア環境の外では、ジェネレーターを完全に制御できます。結果をモックしてそれでジェネレーターを再開することにより、実際の環境をシミュレートできます。モックデータはモック関数やスパイコールよりもはるかに簡単です。