Redux 學習筆記04——使用多個Reducer管理數據

寫在前面

當咱們的系統變得愈來愈複雜的時候,使用一個Reducer函數來管理全局數據,會讓一個Reducer函數變得臃腫,不利於後期的開發和管理。react

好比一個圖書館應用系統,咱們須要管理圖書數據,圖書館管理員數據,讀者數據,借閱記錄數據採購數據等等。若是把這些數據放在一個Reducer中,那麼會形成數據管理的混亂,不利於後期的維護和開發。redux

一個比較好的解決方案是:創建多個Reducer,分別用於管理圖書,管理員,讀者等數據。當咱們須要更新圖書數據的時候,只須要查看管理圖書的Reducer代碼便可,無需關心其餘Reducer。這樣既省時省力,有能夠減小開發中的bug。markdown

下面咱們就來介紹一個若是創建多個Reducer,即如何拆分大的Reducer。數據結構

假設業務場景

好比咱們如今要開發一個圖書館應用,須要對圖書館中的圖書和管理員進行管理。ide

圖書數據管理要求以下:查看圖書列表,向圖書列表中增長新的圖書,從圖書列表中刪除圖書。函數

管理員數據管理要求以下:設置管理員的姓名,角色等信息測試

有了這個簡單的業務場景,咱們開始設置對應的Redux設置吧。ui

建立第一個reducer,管理圖書館管理員的數據

首先咱們須要建立幾個action tye常量,新建UserType.js文件,代碼以下:this

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";
複製代碼

建立按完成以後,使用這些常量定義action,用來調用reducer中的邏輯。新建UserAction.js文件,代碼以下:spa

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
  }
}
複製代碼

最後根據定義reducer函數,用來相應action中的動做,新建UserReducer.js文件,代碼以下:

// 定義原始user數據,reducer的做用就是修改這些數據,而後返回這些數據
const initialUserState = {
    firstName: "",
    lastName: "",
    userRoleList: []
}

// 引入type常量,reducer中收到action發送過來的數據,在reducer中判斷type類型,進行處理
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:
            return state;
    }
}

export default UserReducer;
複製代碼

建立第二個reducer,管理圖書的數據

同理,首先新建BookType.js文件,定義type常量。

export const ADD_NEW_BOOK = "ADD_NEW_BOOK";
export const REMOVE_NEW_BOOK = "REMOVE_NEW_BOOK";
複製代碼

而後使用這些常量定義action,新建BookAction.js文件,代碼以下:

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
  }
}
複製代碼

最後定義reducer,管理圖書信息,新建BookReducer.js文件,代碼以下:

const initialBookState = {
  bookList: ["明朝那些事", "水滸傳"]
}

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;
複製代碼

合併兩個reducer,建立reducer store實例

如今咱們已經建立了兩個reducer,下面須要作的就是把這兩個reducer合併起來,建立一個redux store實例。這裏須要用到 redux 包提供的combineReducers方法,新建Store.js文件,具體代碼以下:

// 引入須要的redux方法
import { createStore, combineReducers } from 'redux'

// 引入定義好的reducer
import BookReducer from './BookReducer'
import UserReducer from './UserReducer';

// 使用該方法合併兩個reducer
const rootReducer = combineReducers({
  BookReducer,
  UserReducer
});

// 使用合併後的reducer建立store實例
const Store = createStore(rootReducer)

export default Store;
複製代碼

使用多個reducer建立的store實例,數據結構是怎樣的

如今咱們已經建立了reduxe實例,能夠在一個組件中獲取redux中的數據,看下此時的數據結構是怎樣的,組件代碼以下:

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(() => {
			// 打印出redux中的數據
      console.log("Redux data: ", Store.getState());
      this.setState((preState, props) => ({
        ...preState,
        ...Store.getState()
      }));
    });
  }

  render() {
    return (
      <div> 測試頁面 </div>
    );
  }

}

export default Login;
複製代碼

在控制檯中,咱們能夠看到redux中的數據結構以下:

{
    "UserReducer": {
        "firstName": "",
        "lastName": "",
        "userRoleList": []
    },
    "BookReducer": {
        "bookList": [
            "明朝那些事",
            "水滸傳"
        ]
    }
}
複製代碼

瞭解redux的數據結構,在後期獲取這些數據的時候,咱們就不會出錯了。

如何修改其中一個reducer管理的數據

如今數據有了,咱們還要可以修改多個reducer的數據,其實很是簡單。雖然咱們定義了兩個reducer,可是徹底看做是一個reducer,在修改數據的時候遵循這樣的流程:引入action,而後觸發action。好比下面的代碼實例:

import React from 'react';
import Store from "myRedux/Store";

// 引入action
import { setFirstName, setLastName } from "myRedux/UserAction";

const LeftSideBar = () => {

  const modifyUserName = () => {
    // 觸發action
    Store.dispatch(setFirstName("Allen"));
    Store.dispatch(setLastName("Feng"));
  }
  
  return (
    <div> <button className="icon" onClick={modifyUserName} ></button> </div>
  );
}

export default LeftSideBar;
複製代碼

寫在最後

如何建立多個reducer來管理redux數據,個人心得就是上述這些。在一些很大的項目中,建立多個reduxer能夠幫助咱們清晰明瞭的管理redux中的數據,這一點但願你們能夠嘗試一下。

相關文章
相關標籤/搜索