DEV Community

Mohammad Abu Musa RABIUL
Mohammad Abu Musa RABIUL

Posted on

React-Redux-Saga: State management of CRUD operations

In this section, we will look into state management of CRUD operations using Redux. To manage and access external resources, Redux-Saga will be used.

What is Redux-Saga?

Redux-Saga is a middleware library used to allow a redux store asynchronously to interact with resources outside of itself. This includes making HTTP requests to external services, accessing browser storage, and executing I/O operations.

Firstly, define actions as follow:

import { GET_POSTS, ADD_POST, DELETE_POST, UPDATE_POST } from "./actionTypes"; export const getPosts = () => { return { type: GET_POSTS, }; }; export const addPost = (data) => { return { type: ADD_POST, payload: data }; }; export const updatePost = (data) => { return { type: UPDATE_POST, payload: data }; }; export const deletePost = (id) => { return { type: DELETE_POST, payload: id }; }; 
Enter fullscreen mode Exit fullscreen mode

Let's define reducer methods. For an example, getPosts reducer is defined as follow:

import * as actionType from "../actions/actionTypes"; const initialState = { posts: [] }; export default function (state = initialState, action) { switch (action.type) { case actionType.GOT_POSTS: { return { ...state, posts: action.payload, }; } default: { return { ...state }; } } } 
Enter fullscreen mode Exit fullscreen mode

Now, combine all the reducers.

import { combineReducers } from "redux"; import addPost from "./addPost"; import getPosts from "./getPosts"; import updatePost from "./updatePost"; import deletePost from "./deletePost"; export default combineReducers({ addPost, getPosts, updatePost, deletePost }); 
Enter fullscreen mode Exit fullscreen mode

It's time to define our sagas. Let's do it to fetch blog posts.
Create a getPosts saga. It works as follow:

  1. On receiving GET_POSTS action it invokes fetchPosts method. fetchPosts invokes the getAll api service method and pass the response data to another action method GOT_POSTS.
import { put, call, takeEvery } from "redux-saga/effects"; import * as actionType from "../actions/actionTypes"; import postsblogPostApi from "../../server/api"; export default function* getPostsSaga() { yield takeEvery(actionType.GET_POSTS, fetchPosts); } function* fetchPosts() { try { const postsResponse = yield call(postsblogPostApi.getAll); yield put({ type: actionType.GOT_POSTS, payload: postsResponse }); } catch (err) { console.log(err); } } 
Enter fullscreen mode Exit fullscreen mode
  1. Add this saga to redux middleware.
import { createStore, applyMiddleware, compose } from "redux"; import createSagaMiddleware from "redux-saga"; import rootReducer from "./reducers/index"; import { getPostsSaga, addPostSaga, deletePostSaga, updatePostSaga } from "./sagas"; const sagaMiddleware = createSagaMiddleware(); const reduxDevTools = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(); const middleware = window.__REDUX_DEVTOOLS_EXTENSION__ && process.env.NODE_ENV === "development" ? compose(applyMiddleware(sagaMiddleware), reduxDevTools) : applyMiddleware(sagaMiddleware); export const store = createStore(rootReducer, middleware); sagaMiddleware.run(getPostsSaga); sagaMiddleware.run(addPostSaga); sagaMiddleware.run(updatePostSaga); sagaMiddleware.run(deletePostSaga); 
Enter fullscreen mode Exit fullscreen mode
  1. Now, wrap our App component using Provider component and pass store redux object. Let's modify index.js file.
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import './index.css'; import App from './App'; import { store } from './redux/store' ReactDOM.render( <React.StrictMode> <Provider store={store}> <App /> </Provider>  </React.StrictMode>,  document.getElementById('root') ); 
Enter fullscreen mode Exit fullscreen mode

Access redux state

Wrap BlogPost component with connect HOC and pass mapStateToProps and mapDispatchToProps.

const mapStateToProps = (state) => { return ({ posts: state.getPosts.posts, addedPost: state.addPost.post, deletedPost: state.deletePost.post, updatedPost: state.updatePost.post }) }; const mapDispatchToProps = (dispatch) => ({ actions: { getPosts: () => { dispatch(actionType.getPosts()); }, addPost: (payload) => { dispatch(actionType.addPost(payload)); }, deletePost: (payload) => { dispatch(actionType.deletePost(payload)); }, updatePost: (payload) => { dispatch(actionType.updatePost(payload)); } }, }); export default connect(mapStateToProps, mapDispatchToProps)(BlogPost); 
Enter fullscreen mode Exit fullscreen mode

We can get redux states from BlogPost component's props object.

const BlogPost = (props) => { const { posts, addedPost, deletedPost, updatedPost, actions } = props; ....... 
Enter fullscreen mode Exit fullscreen mode

You can find the project here

Project Demo

Top comments (0)