ReduxSagas.md 3.0 KB

Using Sagas

https://redux-saga.github.io/redux-saga/docs/introduction/BeginnerTutorial.html

  • Sagas connect as middleware to a redux store.
  • 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')
    }
    

Saga helpers

  • Yield 'effects', in 'redux-saga/effects'
  • takeEvery handles every action of a type that is dispatched.
  • Allows multiple incrementAsync instances to be started concurrently.
  • takeLatest in contrast only takes the response of the latest requested action.
  • Allows only one incrementAsync to run at a time
  • If another task is requested, the previous is automatically cancelled.
  • You can start multiple sagas which behave like they were forked.

Declarative effects

  • Effects are plain JavaScript objects expressing Saga logic.
  • they contain information to be interpreted by the middleware.
  • Sagas can yield effects in multiple forms, the easiest are promises
  • Use call 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.
  • For testing, you can just check whether the effect object ist correct, you don't need to actually call the async function.

Dispathing actions to the store