44
Redux + ReactJs 範範範 : ES6 範範範

Redux+react js

  • Upload
    -

  • View
    638

  • Download
    2

Embed Size (px)

Citation preview

Page 1: Redux+react js

Redux + ReactJs範例為 : ES6 所撰寫

Page 2: Redux+react js

大綱• Redux 概觀• Redux 的哲學• Redux 元件解析• React-Redux• 進階探討

Page 3: Redux+react js

Redux 的概觀Action

Creators Store ReducersAction

Previous State

new State

• Action Creators 產生 Action• Store 呼叫對應的 Reducer 進行處理• Reducer 將處理完畢後的新 State 回傳給

Store

Page 4: Redux+react js

Redux 的相關資訊• Redux 本是即是一個狀態管理的框架• 本身受到 Facebook 所提出的 Flux 框架影響頗深• Redux 並非是為了特定現在流行的 Js 框架而設計 , 單純是為了達成以下功能 :• 系統的狀態管理• 關注點分離 (SoC)• Pure function programming 導向

Page 5: Redux+react js

Redux 作者• 作者 : Dan Abramov• 居住地 : London, UK• 目前在 Facebook 服務• Github 網址 : https://github.com/gaearon• Redux 免費教學 :

https://egghead.io/series/getting-started-with-redux

Page 6: Redux+react js

Redux 的哲學• Redux 借鑑聚合運算 – Reduce• 綜觀整個系統的運作 , 其實不過就是依使用者的操作讓狀態不斷的改變• 改變狀態的運算就如同聚合運算 Reduce 的本意 ; 讓狀態值的變化不斷的收斂

Page 7: Redux+react js

為什麼要選擇 Redux• 解決 Js 狀態管理有許多套件可以選擇 , 例 : Immutable.js• 選擇 Redux 的原因在於當系統屬於大型系統時 , 其狀態物件也會隨之複雜 , 需要有個更為彈性的框架來處理• 彈性 !? 那是啥 ?

Page 8: Redux+react js

Redux 適用場景• 系統好大好複雜

( 太小的請不要用 )• 可以詢問一下自己 , 真的需要用 Redux 嗎 ?

Page 9: Redux+react js

Redux 的彈性來源 -Separate of Concern(SoC)• Redux 利用責任分擔 (Delegation) 來製造彈性• 每個 Redux 的元件都僅負責單一的工作項目• 隨時可以擴充和修改某個元件 , 而不用擔心會影響到系統的其它元件

Page 10: Redux+react js

Redux 熱門的原因• Redux 中每個元件的撰寫都極其簡單 , 皆是以 Js 原生語法作為主體• Redux 達到 Flux 的效果 , 但是其學習曲線卻不高• Redux 可以輕鬆地與任何 Js 框架結合 , 包含 : AngularJs 2 …

Page 11: Redux+react js

Redux 元件解析• Redux 一共只有三個元件 :• Action Creator• Store• Reducer

Page 12: Redux+react js

Redux 元件 – Action Creator• Action Creator 本體是一個 Js 函數 , 其回傳一個 Action 物件• Action 物件是一個原生的 Js 物件 , 但其必定要有一個 type 屬性 ,其餘屬性可以依需求添加• Action 會成為 Reducer 的輸入參數

Action Creator 範例Action 物件

Page 13: Redux+react js

Redux 元件 -Reducer• 本身為一個單純的 Js 函數 , 但其有固定的兩個輸入參數 :• State: 初始狀態物件• Action: ActionCreator 所產生的 Action 物件

• Reducer 僅處理狀態的變更 , 並且在函數執行的最後回傳新的狀態物件( 建議使用 Object.assign 這個 es6 的功能來處理 )• Reducer 可以是僅專注在處理狀態物件中某些屬性 , 也可以在其中撰寫 Switch-case; 依 action 的 type 值 , 而進行不同的處理• 當有多個 Reducer 時 , 可以使用 combineReducers 將它們合併成一個

Page 14: Redux+react js

Redux 元件 -Reducer 範例1. State : Store 的當前狀態物件2. Action : 由 Component 傳遞來的 action 物件3. Action.type : action 的類型4. New State : 以 Object.assign 回傳新的物件

1 2

3

4

Page 15: Redux+react js

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( 初始狀態物件 )

Page 16: Redux+react js

Redux 元件 -Store 範例• 以 reducer 作為參數

1

2

3

1. 訂閱 State 變化事件2. Dispatch action 物件3. 結束訂閱

Page 17: Redux+react js

React-Redux• Redux 本身並非是為了 React 而打造的 , 因此 ,若要與 React協作 ,則勢必會需要一個溝通彼此的”橋”

Page 18: Redux+react js

添加 React-Redux 之後…•除了原本 Redux 的元件之外 ,還多了兩個需要特別題的元件 :• Connect• Provider

Page 19: Redux+react js

回望 ReactJs• ReactJs 本身僅是一個 View 相關的 Library• 當畫面複雜時 , 需要的 Component 以及 Component 之間的組成就更為複雜• ReactJs 建議採用 mediator pattern( 中介者樣式 )

• 狀態只保存在最頂層的 Component• 所有改變狀態的方法邏輯都由最頂層 Component 提供• 底層 Component 僅負責繪出畫面

Page 20: Redux+react js

ReactJs 為何需要 Redux• 當畫面的使用者互動越友善 , 其頂層 Component 就需要更複雜的狀態物件結構 , 以及一沱的狀態改變方法邏輯

(Bad Smell)• Redux 由 Store 負責管理狀態物件 , 改變狀態的方法即是一個個的

Reducer, 原本都由最頂層 Component 負責 , 現在可以完全釋放了

Page 21: Redux+react js

Connect• 由於 Component已經沒有保存狀態 ,故 , 它需要由 Redux 將資料以

Props 傳入 ,藉此讓 Component重繪畫面• Connect具有兩個輸入參數 ( 型別皆為函數 ):• mapStateToProps : 將 Store 的狀態轉型成特定結構的物件 ,再傳遞給

Component• mapDispatchProps : 提供以 dispatch 作為邏輯的方法物件 ,再傳遞給

Component 成為 Props 傳給 Component

成為 Props 傳給 Component

Page 22: Redux+react js

Provider• 當呼叫 ReactDOM 的 render方法時 ,Component才會被真正進行處理• Provider 如同一個 Root Component, 它接收 Redux 的 Store 作為參數 , 並傳遞給開發人員所撰寫的 Component

Page 23: Redux+react js

React-Redux 運作

友善連結

Page 24: Redux+react js

進階探討•若僅只是瞭解上述的概念 , 是不足以實戰的 !• 進階探討才是實戰 !

Page 25: Redux+react js

討論一 : 同步 / 非同步• 在 Modern WebSite 中 , 在前端使用 Ajax 呼叫後端 API 來取得資料 ,成為了一門顯學•若要能夠讓 React-Redux 可以處理 Ajax 的非同步處理 , 需要從

Redux 的 Middleware( 中間層 )著手• 這一切都是因為 Redux 的 Store預設上是僅能接受 Js 原生物件 ,若是非同步處理 ,勢必會遇見 Promise 物件或是特定的處理方式 ,這是原始 Redux 所不能相容的…

Page 26: Redux+react js

React-Redux 運作 : Middleware

友善連結

Page 27: Redux+react js

Redux 的元件 -Middleware• Middleware 主要在於處理 Action• 當 Component觸發 dispatch(ActionCreator()) 之後 ,Action 會在被派送的過程中由 Middleware 一層層的處理 , 其概念就如同 :• ASP.Net MVC/WebAPI : ActionFilter• J2EE : Filter• NodeJs : Middleware

Page 28: Redux+react js

該怎麼寫 Middleware?• 在 Middleware 中可以採取不同的結束模式 :• 傳遞給下一個 Middleware, 如 : next(action)• 跳過某些 Middleware, 如 : dispatch(action)• 直接結束 , 如 : return

• 用 npm找套件比較快… .

Page 29: Redux+react js

常用的 Middleware 套件• Redux-thunk : 允許 action 可以是一個函數 , 用來啟動非同步• Redux-promise : action 本身就是一個 Promise 物件• Redux-logger : action 為一個 Js 物件 , 可用來紀錄 action 和

nextState

Page 30: Redux+react js

以 Redux-Thunk 來解決非同步問題 -觀念解析• 對於 Ajax 處理來說 , 它有 3 個重要的事件 :

• 實際上會有兩組 action; 一組是上述的三個事件型 action,另一組則是實際上的 ajax action

[ 成功 ][失敗 ]

12

3

• Ajax 呼叫開始• Ajax 呼叫結束 -失敗• Ajax 呼叫結束 - 成功

Page 31: Redux+react js

簡單範例 -Action

Ajax觸發事件 -Action Ajax-Action

友善連結

Page 32: Redux+react js

簡單範例 -Reducer

友善連結

1

2

3

1. 非同步程式以 isFetching旗標來告知使用者系統處理現況( 處理中、已完成 )2. 準備發出 Ajax

3. Ajax已結束

Page 33: Redux+react js

簡單範例 -Store

友善連結

1

2

3

1. 引入 redux-thunk 和 redux-logger middleware2. 建構 store 時 , 套用 middleware3. 觸發 fetchPosts 這個 ActionCreator

Page 34: Redux+react js

討論二 : SPA• 在 Google Mail 之後 ,幾乎很多網站都傾向以 SPA(Single Page

Application) 的方式來撰寫網站• ReactJs 本身並不提供 SPA 特性 , 需要額外安裝 React-Router 來達成

Page 35: Redux+react js

React-Router• 是一款以 Component 為導向的路由套件 , 與 ReactJs協作•允許以 JSX 來描述路由之間的關係• React-Router 相依於 History 套件 ,若系統環境 npm版本是 3,則需要額外自行安裝 history 套件

Page 36: Redux+react js

主要的物件• 其實主要都是圍繞在兩個物件 :• Route• Link

• Route 就是用於路由組態之用 ;React-Router 會解析當前 Url, 並且載入路由匹配的元件• 當元件內容需要有類似超鏈結的功能 ,Link 可作為其用

Page 37: Redux+react js

路由匹配• React-Router 的路由允許巢狀•允許部份匹配是可選的•允許參數

參數路由

巢狀路由

Page 38: Redux+react js

預設路由 /鏈結• Reac-Router 提供預設路由 (IndexRoute) 和預設鏈結 (IndexLink)• IndexRoute 用於巢狀情境 ,指定首次載入時的子頁內容是來自那個元件• IndexLink 用於在當其路由字串太過通用時 , 可能會導致被 React-

Router誤判是已被致能 (enable),故提供此元件

Page 39: Redux+react js

路徑語法•絕大多數都是依照 Route 中指定的字串進行比對• 特殊符號

符號 說明: param 匹配一段在 /,?,# 之後的 Url,命中的部份都是參數() 其 () 中的內容為可選項目* 非貪婪 , 可匹配任意字串 ,直到命中下一個字串 ,

或到達 Url尾端

Page 40: Redux+react js

History 物件• React-Router 相依於 History 物件 , 而 History 套件提供 :• createHashHistory• createBrowserHistory• createMemoryHistory

• createHashHistory 為預設的 History 物件 , 其相容於 IE8• createBrowserHistory 是主要推荐使用的 History 物件• createMemoryHistory 用於實現 Server-Side Rendering

Page 41: Redux+react js

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’}

Page 42: Redux+react js

具名路由組態• 可在同一頁中指定並具名組件• 使用具名路由 , 就無法從 this.props.children取得資訊 ( 其為 undefined)

Page 43: Redux+react js

React-Router 下的元件生命週期

Url: / Url: /invoice/123 Url: /invoice/456[跳轉 ] [跳轉 ]

Page 44: Redux+react js

React-Router-Redux• 以實務來說 , 其實 : React + Redux + React-Router 就能夠製做出 SPA的網站 , 但是在某些特定需求下 , 會需要額外再加上

React-Router-Redux•若有下列的特殊狀況 , 可以考慮使用 React-Router-Redux:• 紀錄使用者所有跳轉• 儲存跳轉紀錄• 回放 (Replay) 使用者跳轉操作