Диспатчим action в Store
Следуя предыдущему примеру, предположим, что после каждого сохранения мы хотим отправить какое-либо действие, чтобы уведомить Store о том, что получение данных прошло успешно (в данный момент мы не будем думать о возможных ошибках при получении данных).
Мы могли бы поместить функцию dispatch
в генератор и затем генератор может вызвать его (dispatch) после получения ответа:
// ...
function* fetchProducts(dispatch) {
const products = yield call(Api.fetch, '/products')
dispatch({ type: 'PRODUCTS_RECEIVED', products })
}
Однако это решение имеет те же недостатки, что и функции вызываемые непосредственно изнутри генератора (как было сказано в предыдущем разделе). Если мы хотим проверить, что fetchProducts
выполняет отправку после получения ответа от AJAX, то нам придется опять создавать mock-функцию dispatch
.
Вместо этого нам нужно декларативное решение. Просто создайте объект что бы указать middleware что нам нужно диспачить action и позвольте middleware выполнить настояющию отправку1. Таким образом, мы можем проверить отправку генератора таким же образом: просто проверив полученный эффект через полученый от генератора и убедится, что он содержит правильные инструкции.
Для этой цели библиотека предоставляет функцию put
который диспатчит Effect.
import { call, put } from 'redux-saga/effects'
// ...
function* fetchProducts() {
const products = yield call(Api.fetch, '/products')
// создаем и диспатчим 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')"
)
// создаем фейковый ответ с сервера
const products = {}
// ожидает диспатча
assert.deepEqual(
iterator.next(products).value,
put({ type: 'PRODUCTS_RECEIVED', products }),
"fetchProducts should yield an Effect put({ type: 'PRODUCTS_RECEIVED', products })"
)
Обратите внимание, как мы передаем фейковый ответ генератору с помощью метода next
. Во вне middleware мы имеем полный контроль над генератором, мы можем имитировать реальную среду с простым фейковым результатом и и возабновить генератор с ними. Mocking данные намного проще, чем mock-функции и [spying calls].
1. Just create an Object to instruct the middleware that we need to dispatch some action, and let the middleware perform the real dispatch. ↩