Redux 基礎教程以及結合 React 使用方式

暖生發表於2019-01-08

本文教你實現一個最簡單的 Redux 應用,以及結合 React 如何使用。

Redux簡介

概念

狀態管理工具,使用之後可以清晰的知道應用裡發生了什麼。資料如何修改,如何更新的。

出現的動機

以前我剛接觸 Redux 這類狀態管理工具的時候就在想:為什麼需要這些東西呢,重新整理資料就消失了,也不能持久化儲存資料,有啥用呢? 後來慢慢的應用越做越多,功能越做越複雜,就會發現,很多資料什麼原因修改的,什麼時候修改的,自己是一臉懵逼。啥也想不起來了,維護起來真的痛苦。到了這個時候才發現 Redux 這類工具的厲害之處。名字也很應景的,狀態管理工具。說的很清楚了,就是管理狀態的。讓資料變化過程儘可能的清晰、可預測。

在專案中新增 Redux 並不是必須的。請根據專案需求選擇是否引入 Redux

三大原則

  • 單一資料來源 整個應用的 state 被儲存在一棵 object tree 中,並且這個 object tree 只存在於唯一一個 store 中。

  • State 是隻讀的 唯一改變 state 的方法就是觸發 action,action 是一個用於描述已發生事件的普通物件。

  • 使用純函式來執行修改 為了描述 action 如何改變 state tree ,你需要編寫 reducers。

Redux 三要素

  • Action(將要發生的操作)

  • Reducer(根據 action 更新 state,是一個純函式)

    • 提供 combineReducers(reducers) 函式組合多個 reducer
  • 存放 state 資料的 Store(將 action 和 reducer 聯絡到一起的物件)

    • 提供 getState() 方法獲取 state

    • 提供 dispatch(action) 方法更新 state

    • 通過 subsctibe(listener) 註冊監聽器

    • 通過 subscribr(listener) 返回的函式登出監聽器

示例程式碼

說了這邊文章是教你建立一個最簡單的 Redux 應用,那我們下面就看看使用一個 Redux 到底能有多簡單,多快呢。

使用前先引入 Redux:npm install redux -S

  • 先來個 Action 三要素之一不就是有 Action 麼,有我們就先寫一個 Action 建立函式唄

    Action 建立函式,是一個返回 action 的函式,非必須這樣寫,只是更方便移植和複用,建議使用 Action 建立函式來生成 action

    function increment() {
        return {
            type: "INCREMENT"
        }
    }
    複製程式碼
  • 有了Action,還要有 Reducer 來執行更新啊 Reducer 既然必不可少,就在寫一個 Reducer。(這裡可能會有點迷糊,reducer 不是一個物件,而是一個返回更新後 state 的純函式)

    /**
    * counters 就是一個 reducer,根據傳入的 action 的 type 不同,返回一個新的 state 資料
    */
    // 先初始化 state
    const initCounter = 0;
    function counters(state = initCounter, action) {
        switch(action.type) {
            case 'INCREMENT':
                return state ++;
            default:
                return state;
        }
    }
    複製程式碼
  • 還得有一個存放 state 資料的 store 吧 現在要把我們寫好的 Action 和 Reducer 連線起來

    • 先通過 reducer 建立 store
    const { createStore } = require('redux');
    
    const store = createStore(counters);
    複製程式碼
    • 通過 store.dispatch(action) 將 action 傳送給 reducer,更新 state
    store.dispatch(increment());
    複製程式碼
  • 檢視結果

    就這三步,操作完了吧,那我們現在可以看一下結果了

    // 通過 store.getState() 獲取 State 資料
    console.log('counters: ', store.getState());   // => counters: 1
    複製程式碼

過程總結:

建立一個操作指令 action -> 建立一個 reducer -> 通過 createStore(reducer) 建立一個 store -> 通過 store。dispatch(action) 執行 reducer 中的更新操作,更新 store 中的資料。


這些就是 Redux 的核心用法,有沒有感覺很簡單的,有興趣的話可以跟我一起繼續往下,看一看結合 React 該如何使用呢。


結合 React 使用

React-Redux

用來組合 React 和 Redux 配合使用的外掛

以 create-react-app 腳手架為例,請先使用 create-react-app 建立一個本地專案。本例中預設 create-react-app 已全域性安裝過了

$ npm npm init react-app react-redux-todos
$ cd react-redux-todos
複製程式碼

外掛安裝

$ npm install redux react-redux -S
複製程式碼

配合元件使用

  • 在元件根目錄使用 react-redux 提供的 Prodiver 標籤包裹

    import { Provider } from 'react-redux';
    
    <Provider store={ store }>
        ...
    </Provider>
    複製程式碼
  • 在需要用到 state 或 action 的元件中使用 connect 高階元件進行包裝

    import { connect } from 'react-redux';
    import { createAction } from './actions'
    
    // mapStateToProps 編寫方式
    const mapStateToProps = (state) => {
        return {
            reducer: state.reducer
        }
    }
    
    // mapDispatchToProps 編寫方式
    const mapDispatchToProps = (dispatch) => {
        return {
            createAction: text => dispatch(createAction(field));
        }
    }
    
    // 使用 connect 將 state 和 dispatch 包裝到 Component 的屬性中
    export default connect(mapStateToProps, mapDispatchToProps)(Component);
    複製程式碼
  • 在元件中就可以通過 this.props.reducer 和 this.props.createAction 的方式獲取資料以及呼叫 action 了

TodoList 示例

示例程式碼

預覽地址

擴充套件

Reducer 的 combineReducers 方法

當有多個 reducer 時,建立 store 之前需要將它們先進行合併

import { combineReducers } from 'redux';

// 合併成一個 reducers
const reducers = combineReducers({
    a: doSomethingWithA,
    b: processB,
    c: c
});
複製程式碼

Store 的 subscribe 方法

  • 呼叫 store.subsctibe(listener) 註冊監聽事件 store 中的資料發生變化時,就會呼叫 listener 函式

    /**
     * 通過 store.subscribe(function) 註冊一個監聽器。每次 state 更新時,都會列印輸出日誌
     */
    store.subscribe(() => console.log(store.getState()));
    複製程式碼
  • store.subscribe(listener) 的返回值是一個 登出監聽的函式

    /**
     * store.subscribe(func) 會返回一個函式,執行這個函式可以登出監聽器
     */
    // 返回一個函式 unsubscribe
    const unsubscribe = store.subscribe(() => console.log(store.getState()));
    // 執行這個函式可以登出監聽器
    unsubscribe();
    複製程式碼

如果還沒看夠

Redux 中文文件

這裡有關於 Redux 最詳細的介紹和講解,我就不多此一舉了,有興趣的同學可以去看看哈。

相關文章