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
Top comments (0)