Mohammad Abu Musa RABIUL
Posted on September 12, 2021
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
};
};
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 };
}
}
}
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
});
It's time to define our sagas. Let's do it to fetch blog posts.
Create a getPosts
saga. It works as follow:
- On receiving
GET_POSTS
action it invokesfetchPosts
method.fetchPosts
invokes thegetAll
api service method and pass the response data to another action methodGOT_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);
}
}
- 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);
- Now, wrap our
App
component usingProvider
component and pass store redux object. Let's modifyindex.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')
);
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);
We can get redux states from BlogPost
component's props
object.
const BlogPost = (props) => {
const { posts, addedPost, deletedPost, updatedPost, actions } = props;
.......
You can find the project here
Project Demo
Posted on September 12, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.