Writing in the front
When our system becomes more and more complex, using a Reducer function to manage global data will make a Reducer function become bloated, which is not conducive to later development and management.
For example, a library application system, we need to manage book data, librarian data, reader data, borrowing records data procurement data and so on. If these data are put into a Reducer, it will cause confusion in data management, which is not conducive to later maintenance and development.
A better solution is to establish multiple Reducer, which are respectively used to manage books, administrators, readers and other data. When we need to update the book data, we only need to view the Reducer code of the management books and do not need to care about other Reducer codes. This saves time and effort and reduces bugs in development.
Let’s introduce a Reducer if multiple reducers are established, that is, how to split large reducers.
Hypothetical business scenario
For example, we now want to develop a library application, which needs to manage the books and administrators in the library.
The book data management requirements are as follows: View the book list, add new books to the book list, and delete books from the book list.
Requirements for managing administrator data are as follows: Set the administrator’s name and role
With this simple business scenario in hand, let’s start setting up the corresponding Redux Settings.
Create the first Reducer to manage the librarian’s data
First we need to create a few action tye constants and create a new usertype. js file as follows:
export const SET_FIRST_NAME = "SET_FIRST_NAME";
export const SET_LAST_NAME = "SET_LAST_NAME";
export const ADD_NEW_USER_ROLE = "ADD_NEW_USER_ROLE";
export const REMOVE_USER_ROLE = "REMOVE_USER_ROLE";
Copy the code
Once the creation is complete, use these constants to define actions that call the logic in the Reducer. Create a new useraction.js file with the following code:
import { SET_FIRST_NAME, SET_LAST_NAME, ADD_NEW_USER_ROLE, REMOVE_USER_ROLE } from "./UserType"
export const setFirstName = firstName= > {
return {
type: SET_FIRST_NAME,
payload: firstName
}
}
export const setLastName = lastName= > {
return {
type: SET_LAST_NAME,
payload: lastName
}
}
export const addNewUserRole = newUserRole= > {
return {
type: ADD_NEW_USER_ROLE,
payload: newUserRole
}
}
export const removeUserRole = roleName= > {
return {
type: REMOVE_USER_ROLE,
payload: roleName
}
}
Copy the code
Finally, create a UserReducer. Js file according to the defined reducer function, which is used for corresponding actions in the action. The code is as follows:
// Define raw user data. The reducer role is to modify these data and return them
const initialUserState = {
firstName: "".lastName: "".userRoleList: []}// Import the type constant. The reducer receives the data sent by the action. Determine the type in the Reducer and process it
import { SET_FIRST_NAME, SET_LAST_NAME, ADD_NEW_USER_ROLE, REMOVE_USER_ROLE } from "./UserType"
const UserReducer = (state = initialUserState, action) = > {
switch(action.type) {
case SET_FIRST_NAME:
return {
...state,
firstName: action.payload
}
case SET_LAST_NAME:
return {
...state,
lastName: action.payload
}
case ADD_NEW_USER_ROLE:
let newUserRoleList = [...state.userRoleList]
if(! newUserRoleList.includes(action.payload)) { newUserRoleList.push(action.payload) }return {
...state,
userRoleList: newUserRoleList
}
case REMOVE_USER_ROLE:
return {
...state,
userRoleList: state.userRoleList.filter(roleName= >roleName ! == action.payload) }default:
returnstate; }}export default UserReducer;
Copy the code
Create a second Reducer to manage the data of the books
Similarly, start by creating a new bookType.js file and defining the type constant.
export const ADD_NEW_BOOK = "ADD_NEW_BOOK";
export const REMOVE_NEW_BOOK = "REMOVE_NEW_BOOK";
Copy the code
Then use these constants to define actions and create a new bookAction.js file as follows:
import { ADD_NEW_BOOK, REMOVE_NEW_BOOK } from "./BookType";
export const addNewBooks = newBookName= > {
return {
type: ADD_NEW_BOOK,
payload: newBookName
}
}
export const removeNewBooks = bookName= > {
return {
type: REMOVE_NEW_BOOK,
payload: newBookName
}
}
Copy the code
Finally, define reducer, manage the book information, and create a BookReducer. Js file with the following code:
const initialBookState = {
bookList: ["What happened in the Ming Dynasty"."Water Margin"]}import { ADD_NEW_BOOK, REMOVE_NEW_BOOK } from "./BookType";
const BookReducer = (state = initialBookState, action) = > {
if (action.type === ADD_NEW_BOOK) {
return {
...initialBookState,
bookList: [...initialBookState.bookList, action.payload]
}
}
if (action.type === REMOVE_NEW_BOOK) {
return {
...initialBookState,
bookList: initialBookState.bookList.filter(_book= >_book ! == action.payload) } }return state;
}
export default BookReducer;
Copy the code
Merge two reducers and create a Reducer Store instance
Now that we have created two reducers, what we need to do is merge these two reducers and create a Redux Store instance. The combineReducers method provided by redux package is used to create a store. js file. The specific code is as follows:
// Introduce the required redux methods
import { createStore, combineReducers } from 'redux'
// Import the defined reducer
import BookReducer from './BookReducer'
import UserReducer from './UserReducer';
Merge the two reducers using this method
const rootReducer = combineReducers({
BookReducer,
UserReducer
});
Create a Store instance using the reducer
const Store = createStore(rootReducer)
export default Store;
Copy the code
What is the data structure of the store instances created using a Reducer
Now that we have created the reduxe instance, we can retrieve the data from redux in a component. Let’s see what the data structure looks like. The component code looks like this:
import React from 'react'
import Store from 'myRedux/Store'
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount() {
this.setState((preState, props) = >({... preState, ... Store.getState() })); Store.subscribe(() = > {
// Print out the data in redux
console.log("Redux data: ", Store.getState());
this.setState((preState, props) = >({... preState, ... Store.getState() })); }); }render() {
return (
<div>The test page</div>); }}export default Login;
Copy the code
In the console, we can see the following data structure in Redux:
{
"UserReducer": {
"firstName": ""."lastName": ""."userRoleList": []},"BookReducer": {
"bookList": [
"What happened in the Ming Dynasty"."Water Margin"]}}Copy the code
Knowing the data structure of Redux, we will not make mistakes when retrieving the data later.
How do I modify one of the Reducer managed data
Now that we have data, we need to be able to modify multiple reducer data, which is actually very simple. Although we defined two Reducers, they were completely treated as one Reducer. When data was modified, the following flow was followed: actions were introduced and then triggered. For example:
import React from 'react';
import Store from "myRedux/Store";
/ / into the action
import { setFirstName, setLastName } from "myRedux/UserAction";
const LeftSideBar = () = > {
const modifyUserName = () = > {
/ / triggers the action
Store.dispatch(setFirstName("Allen"));
Store.dispatch(setLastName("Feng"));
}
return (
<div>
<button className="icon" onClick={modifyUserName} ></button>
</div>
);
}
export default LeftSideBar;
Copy the code
Write in the last
These are my suggestions on how to create multiple Reducer to manage REdux data. On very large projects, creating multiple Reduxers can help us manage the data in redux in a very straightforward way, which I encourage you to try.