本文教你實現一個最簡單的 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 最詳細的介紹和講解,我就不多此一舉了,有興趣的同學可以去看看哈。