Get started
So we create a ‘store’ folder first.
We import createSagaMiddleware from library redux-saga.
First we create the saga middleware.
1 2 3 |
import createSagaMiddleware from "redux-saga"; ... const sagaMiddleware = createSagaMiddleware(); |
Then we create the store by putting in:
– root reducer
– saga middleware
1 2 3 4 |
const store = createStore( rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware)) ); |
Once the saga middleware is in, we run it.
1 |
sagaMiddleware.run(rootSaga); |
src/store/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import { createStore, applyMiddleware, compose } from "redux"; import createSagaMiddleware from "redux-saga"; import rootReducer from "./reducers"; import rootSaga from "./sagas"; const sagaMiddleware = createSagaMiddleware(); const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware)) ); sagaMiddleware.run(rootSaga); export default store; |
We use this finished created store in our index.js.
We put it on a Provider context so that everything in the middle can see it.
src/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import { BrowserRouter, Routes, Route} from "react-router-dom"; import { Provider } from "react-redux"; import store from "./store"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Provider store={store}> <BrowserRouter> <Routes> <Route path="*" element={ <App /> }> </Route> </Routes> </BrowserRouter> </Provider> ); reportWebVitals(); |
We ran saga middleware with rootSaga, so let’s see what that is.
We import all and fork from redux saga.
all simply runs multiple effects in parallel.
fork creates an effect that instructs the middleware to perform a non-blocking call of PostSaga.
1 2 3 4 5 6 7 8 9 10 11 |
import { all, fork } from "redux-saga/effects"; import PostSaga from "./posts/saga"; export default function* rootSaga() { console.log('rootSaga'); // all: run multiple effects in parallel // fork: Creates an Effect description that instructs the middleware to perform a non-blocking call on fn yield all([fork(PostSaga)]); } |
So what is PostSaga?
It is a function that yield takeLatest of a function whenever an action is triggered.
So let’s explain what it means.
take creates an Effect that instructs the middleware to wait for a specified action on the Store.
The Generator is suspended until an action that matches pattern is dispatched.
The result of yield take(pattern) is an action object being dispatched.
takeLatest Forks a saga on each action (i.e GET_POSTS) dispatched to the Store that matches.
And automatically cancels any previous saga task started previously if it’s still running.
takeLatest doesn’t allow multiple Saga tasks to be fired concurrently.
As soon as it gets a new dispatched action, it cancels any previously-forked task (if still running).
takeLatest can be useful to handle AJAX requests where we want to only have the response to the latest request.
src/store/posts/saga.js
1 2 3 4 5 6 7 8 |
function* CartSaga() { yield takeLatest(GET_POSTS, onGetPosts); // when GET_POSTS action is triggered, let's execute onGEtPosts yield takeLatest(GET_POST_DETAILS, onGetPostDetails); // when GET_POST_DETAILS is triggered, execute onGetPostDetails } export default CartSaga; |
So in other words, we fork CartSaga, which listens to GET_POSTS and GET_POST_DETAILS call their respective handlers in a takeLatest fashion.