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.
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.
//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)
});
};
};
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.
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 })
}
}
Both Redux-Saga and Redux-Thunk have their own use cases.
You should use Redux-Saga for…
You should use Redux-Thunk for…