DEV Community

Mohammad Abu Musa RABIUL
Mohammad Abu Musa RABIUL

Posted on

3

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)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more