https://redux-saga.github.io/redux-saga/docs/introduction/BeginnerTutorial.html
Sagas run like cuncurrent worker tasks and have to be started for that.
// main.js
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import { rootSaga } from './sagas'
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(helloSaga)
Asynchronous actions need to be split into more tasks to the dispatcher, so reducers can always return immediately:
// actions.js
function increment(payload) {
return {
type: 'INCREMENT_REQUEST',
payload
}
}
// reducers.js
export default function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT_REQUEST':
// disable button
// print message
/* YOU DON'T NEED TO CALL THE FUNCTION HERE.
IT'S INTERCEPTED BY THE MIDDLEWARE. */
return state
case 'INCREMENT_SUCCESS':
return state + 1
case 'INCREMENT_FAIL':
// print error message
default:
return state
}
}
// sagas.js
import { call, put, takeEvery } from 'redux-saga/effects'
// Worker
export function * incrementAsync () {
try {
const data = yield call(Api.isIncrementOk)
yield put({ type: 'INCREMENT_SUCCESS', data })
} catch (error) {
yield put({ type: 'INCREMENT_FAIL', error})
}
}
// Watcher (intercepts INCREMENT_REQUEST, dispatches INCREMENT_SUCCESS or INCREMENT_FAIL in return.)
export function * watchIncrementAsync() {
yield takeEvery('INCREMENT_REQUEST', incrementAsync)
}
// export all sagas in parallel
export default function * rootSaga() {
yield takeEvery('INCREMENT_REQUEST')
yield takeEvery('DECREMENT_REQUEST')
}
takeEvery
handles every action of a type that is dispatched.incrementAsync
instances to be started concurrently.takeLatest
in contrast only takes the response of the latest requested action.incrementAsync
to run at a timecall
to call functions. Call returns on object describing to the middleware what to do. This is similar to action creators, which describe actions for the reducer.