umma.dev

Redux-Thunk or Redux-Saga?

There are two types of middleware that can be used when dealing with Redux. This post outlines the differences between the two and when you might choose to use one over the other.

The Middleware in Redux sits between dispatch and reducers. Middleware might be used to make asynchronous requests, dispatch new actions and log actions.

There are two types of middleware you can use in Redux, Saga and Thunk.

Redux-Thunk

Thunk enables you to call action creators which return a function. This function recieves a dispatch method from the store which is used to dispatch actions once asynchronous functions have be completed.

Example

//src/store.js
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers/rootReducer'

export default function configureStore() {
 return createStore(
  rootReducer,
   applyMiddleware(thunk)
 )
}
export const thunkExample = values => {
  return dispatch => {
    return axios.get(url)
      .then(response =>{
        dispatch(example(response));
      })
      .catch(error => {
        console.log(error)
      });
    };
  };

Redux-Saga

Saga uses generators, which is a function that behaves like an iterator. An example of generators is async/await.

An example of a generator

function* generator(i) {
  yield i;
  yield i + 2;
}

const gen = generator(10);

console.log(gen.next().value);
// 10

console.log(gen.next().value);
// 12

Generators can be utilised to write asynchronous code that looks synchronous.

Example

export const sagaThunk = values => {
  return async dispatch => {
    try {
      const response = await axios.get(url);
      dispatch(example(response));
    }
    catch(error) {
      dispatch(example(error));
    }
  };
};

Root Saga

import { all } from 'redux-saga/effects'
import WatcherSaga from './Saga'
export default function* rootSaga() {
  yield all([
    WatcherSaga(),
  ])
}

Watcher Sagas

import { takeLatest, select, call, put } from 'redux-saga/effects'
import { getData } from '../services/'
export default function* watchAction() {
  yield takeLatest('ACTION', workerSaga )
}
export function* workerSaga(action) {
  try {
    const thingsFromReduxStore = yield select(state => state.data)
    const { anAction } = action.data
    const payload = { anAction }
    const data = yield call(getData, payload)
    yield put({ type: 'ACTION_RESPONSE', data })}
    catch (error) {
        yield put({ type: 'ACTION_ERROR', error })
    }
}

Which One is Better?

Both Redux-Saga and Redux-Thunk have their own use cases.

You should use Redux-Saga for…

  • Complex tasks such as login
  • Waiting for certain functionality to happen
  • Have functionality that works in the background

You should use Redux-Thunk for…

  • API calls (AJAX, Axios etc.)
  • Data uses
  • Simple async functionality