redux+react js
TRANSCRIPT
Redux + ReactJs範例為 : ES6 所撰寫
大綱• Redux 概觀• Redux 的哲學• Redux 元件解析• React-Redux• 進階探討
Redux 的概觀Action
Creators Store ReducersAction
Previous State
new State
• Action Creators 產生 Action• Store 呼叫對應的 Reducer 進行處理• Reducer 將處理完畢後的新 State 回傳給
Store
Redux 的相關資訊• Redux 本是即是一個狀態管理的框架• 本身受到 Facebook 所提出的 Flux 框架影響頗深• Redux 並非是為了特定現在流行的 Js 框架而設計 , 單純是為了達成以下功能 :• 系統的狀態管理• 關注點分離 (SoC)• Pure function programming 導向
Redux 作者• 作者 : Dan Abramov• 居住地 : London, UK• 目前在 Facebook 服務• Github 網址 : https://github.com/gaearon• Redux 免費教學 :
https://egghead.io/series/getting-started-with-redux
Redux 的哲學• Redux 借鑑聚合運算 – Reduce• 綜觀整個系統的運作 , 其實不過就是依使用者的操作讓狀態不斷的改變• 改變狀態的運算就如同聚合運算 Reduce 的本意 ; 讓狀態值的變化不斷的收斂
為什麼要選擇 Redux• 解決 Js 狀態管理有許多套件可以選擇 , 例 : Immutable.js• 選擇 Redux 的原因在於當系統屬於大型系統時 , 其狀態物件也會隨之複雜 , 需要有個更為彈性的框架來處理• 彈性 !? 那是啥 ?
Redux 適用場景• 系統好大好複雜
( 太小的請不要用 )• 可以詢問一下自己 , 真的需要用 Redux 嗎 ?
Redux 的彈性來源 -Separate of Concern(SoC)• Redux 利用責任分擔 (Delegation) 來製造彈性• 每個 Redux 的元件都僅負責單一的工作項目• 隨時可以擴充和修改某個元件 , 而不用擔心會影響到系統的其它元件
Redux 熱門的原因• Redux 中每個元件的撰寫都極其簡單 , 皆是以 Js 原生語法作為主體• Redux 達到 Flux 的效果 , 但是其學習曲線卻不高• Redux 可以輕鬆地與任何 Js 框架結合 , 包含 : AngularJs 2 …
Redux 元件解析• Redux 一共只有三個元件 :• Action Creator• Store• Reducer
Redux 元件 – Action Creator• Action Creator 本體是一個 Js 函數 , 其回傳一個 Action 物件• Action 物件是一個原生的 Js 物件 , 但其必定要有一個 type 屬性 ,其餘屬性可以依需求添加• Action 會成為 Reducer 的輸入參數
Action Creator 範例Action 物件
Redux 元件 -Reducer• 本身為一個單純的 Js 函數 , 但其有固定的兩個輸入參數 :• State: 初始狀態物件• Action: ActionCreator 所產生的 Action 物件
• Reducer 僅處理狀態的變更 , 並且在函數執行的最後回傳新的狀態物件( 建議使用 Object.assign 這個 es6 的功能來處理 )• Reducer 可以是僅專注在處理狀態物件中某些屬性 , 也可以在其中撰寫 Switch-case; 依 action 的 type 值 , 而進行不同的處理• 當有多個 Reducer 時 , 可以使用 combineReducers 將它們合併成一個
Redux 元件 -Reducer 範例1. State : Store 的當前狀態物件2. Action : 由 Component 傳遞來的 action 物件3. Action.type : action 的類型4. New State : 以 Object.assign 回傳新的物件
1 2
3
4
Redux 元件 -Store• Store 掌控狀態物件• 一個 Redux 系統僅只有一個 Store; Action Creator 和 Reducer 都是多個• Store 提供 3 個 API:• API : getState() – 取得當前 Store 中的狀態• API : subscribe(FnLis) – 註冊 Store 狀態改變的傾聽器 (Listener)• API : dispatch – 提供與 Redux 結合的前端框架資料流觸發的關鍵函數
• Store 是靠 createStore 這個函數所創建 , 其輸入參數為 :• Reducer• Initial State Object( 初始狀態物件 )
Redux 元件 -Store 範例• 以 reducer 作為參數
1
2
3
1. 訂閱 State 變化事件2. Dispatch action 物件3. 結束訂閱
React-Redux• Redux 本身並非是為了 React 而打造的 , 因此 ,若要與 React協作 ,則勢必會需要一個溝通彼此的”橋”
添加 React-Redux 之後…•除了原本 Redux 的元件之外 ,還多了兩個需要特別題的元件 :• Connect• Provider
回望 ReactJs• ReactJs 本身僅是一個 View 相關的 Library• 當畫面複雜時 , 需要的 Component 以及 Component 之間的組成就更為複雜• ReactJs 建議採用 mediator pattern( 中介者樣式 )
• 狀態只保存在最頂層的 Component• 所有改變狀態的方法邏輯都由最頂層 Component 提供• 底層 Component 僅負責繪出畫面
ReactJs 為何需要 Redux• 當畫面的使用者互動越友善 , 其頂層 Component 就需要更複雜的狀態物件結構 , 以及一沱的狀態改變方法邏輯
(Bad Smell)• Redux 由 Store 負責管理狀態物件 , 改變狀態的方法即是一個個的
Reducer, 原本都由最頂層 Component 負責 , 現在可以完全釋放了
Connect• 由於 Component已經沒有保存狀態 ,故 , 它需要由 Redux 將資料以
Props 傳入 ,藉此讓 Component重繪畫面• Connect具有兩個輸入參數 ( 型別皆為函數 ):• mapStateToProps : 將 Store 的狀態轉型成特定結構的物件 ,再傳遞給
Component• mapDispatchProps : 提供以 dispatch 作為邏輯的方法物件 ,再傳遞給
Component 成為 Props 傳給 Component
成為 Props 傳給 Component
Provider• 當呼叫 ReactDOM 的 render方法時 ,Component才會被真正進行處理• Provider 如同一個 Root Component, 它接收 Redux 的 Store 作為參數 , 並傳遞給開發人員所撰寫的 Component
進階探討•若僅只是瞭解上述的概念 , 是不足以實戰的 !• 進階探討才是實戰 !
討論一 : 同步 / 非同步• 在 Modern WebSite 中 , 在前端使用 Ajax 呼叫後端 API 來取得資料 ,成為了一門顯學•若要能夠讓 React-Redux 可以處理 Ajax 的非同步處理 , 需要從
Redux 的 Middleware( 中間層 )著手• 這一切都是因為 Redux 的 Store預設上是僅能接受 Js 原生物件 ,若是非同步處理 ,勢必會遇見 Promise 物件或是特定的處理方式 ,這是原始 Redux 所不能相容的…
Redux 的元件 -Middleware• Middleware 主要在於處理 Action• 當 Component觸發 dispatch(ActionCreator()) 之後 ,Action 會在被派送的過程中由 Middleware 一層層的處理 , 其概念就如同 :• ASP.Net MVC/WebAPI : ActionFilter• J2EE : Filter• NodeJs : Middleware
該怎麼寫 Middleware?• 在 Middleware 中可以採取不同的結束模式 :• 傳遞給下一個 Middleware, 如 : next(action)• 跳過某些 Middleware, 如 : dispatch(action)• 直接結束 , 如 : return
• 用 npm找套件比較快… .
常用的 Middleware 套件• Redux-thunk : 允許 action 可以是一個函數 , 用來啟動非同步• Redux-promise : action 本身就是一個 Promise 物件• Redux-logger : action 為一個 Js 物件 , 可用來紀錄 action 和
nextState
以 Redux-Thunk 來解決非同步問題 -觀念解析• 對於 Ajax 處理來說 , 它有 3 個重要的事件 :
• 實際上會有兩組 action; 一組是上述的三個事件型 action,另一組則是實際上的 ajax action
[ 成功 ][失敗 ]
12
3
• Ajax 呼叫開始• Ajax 呼叫結束 -失敗• Ajax 呼叫結束 - 成功
簡單範例 -Reducer
友善連結
1
2
3
1. 非同步程式以 isFetching旗標來告知使用者系統處理現況( 處理中、已完成 )2. 準備發出 Ajax
3. Ajax已結束
簡單範例 -Store
友善連結
1
2
3
1. 引入 redux-thunk 和 redux-logger middleware2. 建構 store 時 , 套用 middleware3. 觸發 fetchPosts 這個 ActionCreator
討論二 : SPA• 在 Google Mail 之後 ,幾乎很多網站都傾向以 SPA(Single Page
Application) 的方式來撰寫網站• ReactJs 本身並不提供 SPA 特性 , 需要額外安裝 React-Router 來達成
React-Router• 是一款以 Component 為導向的路由套件 , 與 ReactJs協作•允許以 JSX 來描述路由之間的關係• React-Router 相依於 History 套件 ,若系統環境 npm版本是 3,則需要額外自行安裝 history 套件
主要的物件• 其實主要都是圍繞在兩個物件 :• Route• Link
• Route 就是用於路由組態之用 ;React-Router 會解析當前 Url, 並且載入路由匹配的元件• 當元件內容需要有類似超鏈結的功能 ,Link 可作為其用
路由匹配• React-Router 的路由允許巢狀•允許部份匹配是可選的•允許參數
參數路由
巢狀路由
預設路由 /鏈結• Reac-Router 提供預設路由 (IndexRoute) 和預設鏈結 (IndexLink)• IndexRoute 用於巢狀情境 ,指定首次載入時的子頁內容是來自那個元件• IndexLink 用於在當其路由字串太過通用時 , 可能會導致被 React-
Router誤判是已被致能 (enable),故提供此元件
路徑語法•絕大多數都是依照 Route 中指定的字串進行比對• 特殊符號
符號 說明: param 匹配一段在 /,?,# 之後的 Url,命中的部份都是參數() 其 () 中的內容為可選項目* 非貪婪 , 可匹配任意字串 ,直到命中下一個字串 ,
或到達 Url尾端
History 物件• React-Router 相依於 History 物件 , 而 History 套件提供 :• createHashHistory• createBrowserHistory• createMemoryHistory
• createHashHistory 為預設的 History 物件 , 其相容於 IE8• createBrowserHistory 是主要推荐使用的 History 物件• createMemoryHistory 用於實現 Server-Side Rendering
React-Router 的頁面跳轉• 元件會在 Url跳轉時 ,接收到 React-Router 所傳遞的參數 :
• children : 子元件的內容• params : QueryString 參數• location : 當前的 localtion 物件• history : 可用 history 物件在程式中控制頁面挑轉• route : 渲染當前元件的 Route 物件• routeParams: 與 params 不同在於 ;routeParams 僅只有 routing pattern字串所定義的部份 , 而 params 會一概視為參數
例如 : 定義 routing pattern 為 users/:Id, 而 Url 當前為 /users/123/name/john,則this.props.routeParams 為 {Id:’123’}this.props.params 為 {Id:123, name: ‘john’}
具名路由組態• 可在同一頁中指定並具名組件• 使用具名路由 , 就無法從 this.props.children取得資訊 ( 其為 undefined)
React-Router 下的元件生命週期
Url: / Url: /invoice/123 Url: /invoice/456[跳轉 ] [跳轉 ]
React-Router-Redux• 以實務來說 , 其實 : React + Redux + React-Router 就能夠製做出 SPA的網站 , 但是在某些特定需求下 , 會需要額外再加上
React-Router-Redux•若有下列的特殊狀況 , 可以考慮使用 React-Router-Redux:• 紀錄使用者所有跳轉• 儲存跳轉紀錄• 回放 (Replay) 使用者跳轉操作