Redux

Redux is a predictable state container for JavaScript apps.

https://github.com/reduxjs/redux

https://cdnjs.cloudflare.com/ajax/libs/redux/3.3.1/redux.js

概念

view 點擊 => action => reducer => store => 回傳 state 給 view

1.state 統一由 store 保存,任何更新 state 都要告知 store

2.讓 views 得到 store 中 state的方法

1.使用connect讓最上層元件取得Provider中的store,再用props傳下去

2.使用store.getState

簡單範例

<!DOCTYPE html>
<html>
  <head>
    <title>Redux basic example</title>
    <script src="https://npmcdn.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>
    <div>
      <p>
        Clicked: <span id="value">0</span> times
        <button id="increment">+</button>
        <button id="decrement">-</button>
        <button id="incrementIfOdd">Increment if odd</button>
        <button id="incrementAsync">Increment async</button>
      </p>
    </div>
     </body>
</html>

Reducer

使用React連結Redux

https://github.com/reactjs/redux/tree/master/examples/counter

建立counter的元件(原本的HTML)

render到html

最後定義reducer

完成

上例我們沒有直接去定義action.js而是直接指定action的type

我們可改寫成

action.js

另一個稍為更詳細的範例

流程:

實做:

1.

package.json

新增後輸入npm install

2.

webpack.config.js

3.

新增server 資料夾,裡面放入server.js

4.

新client資料夾,裡面放入index.html

以及,client.js

Provider用來連結react即redux的store

5.

新增redux資料夾

裡面放入三個檔案

store.js action.js reducer.js

store.js

這裡我們加入了中間件logger

而store的必要參數為reducer,我們用import reducer from './reducer'傳入

action.js

reducer.js

最後建立component資料夾

裡面放入App.js TodoInput.js TodoList.js

App.js

從chrome React dev tool可以看到如果使用connect

App元件可以接到從store來的state且轉成他的props

TodoInput.js

TodoList.js

完整版:(於master branch)

https://github.com/EasonWang01/Redux-tutorial

接著幫他加上toggle

使點選後判斷完成了沒,來讓事項有一橫線

1.先在action.js

2.reducer.js

最後在TodoList.js

完整版在 branch toggle

接著加入三個選項,分別顯示all,active,completed

1.新增FilterLink.js

2.將他加入TodoList.js

更改action.js

以及reducer.js

(此時多了三個選項,且點擊會發出action)

3.接著我們幫他加入發出action後所要做的事

我們會使用array的filter方法,過濾出state.todos中completed為false的方法

(給點擊active按鈕用)反之為給completed按鈕用

(filter()讓array中每個元素接受一個function的運算且return一個值,為true或false) (如果為true則繼續保留在array)

在這之前

我們先幫reducer加上一個狀態

接著將App.js改為

(因為我們現在state裡不只一個state,所以先傳入整包,於子代再做取出)

最後

(把原本傳入最後return要map的物件先做過濾)

TodoList.js

使用bind是因為我們在function內想取得class的執行環境,所以把他綁到this

3.接著

讓點擊後的link變黑色,無法重複點擊

所以先幫FilterLink加上一個props

之後點擊link後去偵測,這個link的filter props和當前store的filter屬性如符合的話,則只回傳普通的文字

使用combined reduecer

在這之前,我們先改變我們reducer的寫法

(上面,我們將reducer寫成兩個function)

combined reducer即是這個概念,所以我們把reducer.js 改為如下

兩個重點

最後,在ES6在物件的key跟value名稱相同時可省略

所以寫成

在多人合作中,我們會把reducer每個function放在不同檔案,最後再import到rootReducer來減少多人一起開發功能時的conflict

中間件 BindActionCreator

將store 的dispatch 包住action 成為function 可直接使用 不用再dispatch(someaction)

App.js加上

即可發現點選React devtool中App的props的dispatch變為actions物件

1.

原本父元件使用this.props.dispatch將dispatch方法傳下去,現在改為用this.props.actions

2.

而VIEW發送ACTION的方式從

改為

但一般我們不會用上面這種寫法

mapDispatchToProp

建議如下寫法

https://egghead.io/lessons/javascript-redux-using-mapdispatchtoprops-shorthand-notation

操作非同步動作(Async)

例如:

我們今天有一個按鈕,點擊後發出action去跟server要資料,回傳資料後再觸發一個action去更新state

使用Redux-thunk

npm install redux-thunk

將store.js改為

之後我們action.js裡面寫的方法不只可以return物件,還可以return function

這個function就是用來寫非同步API,最後拿回資料再寫return,之後即會送到reducer處理

例如:

PS:

在action.js內可以直接調用store的所有方法,因為我們action是由store發出的 ex:store.dispatch(action.toggleTodo(a.id));

React-router-redux

用途:將Redux結合react-router

安裝 npm install --save react-router-redux

1.在使用combind reducer的地方加上

2.將client.js加上

完整版

最後將App.js改為

使用React.cloneElement原因為,原本react-router要顯示子帶router必須用{this.props.children}但這樣原本的prop沒辦法往下傳

所以使用React.cloneElement即可在子代傳入props

記得加條件限制

但是,如果url為http://localhost:3000/

這時 {React.cloneElement(this.props.children, { todos:this.props })}

中的this.props.children為null,所以會報錯

須改為

Redux Devtools

1.到chrome extension 下載Redux Devtools

2.在程式的store.js中改為如下

3.開啟網頁即可看到chrome extension的redux devtools亮起,即可點選開啟

stateless function components

(可將class改為const)

官方推薦使用

https://facebook.github.io/react/docs/reusable-components.html#stateless-functions

https://medium.com/@joshblack/stateless-components-in-react-0-14-f9798f8b992d#.nyhbdhy1j

因為Redux 的state統一存在store中,所以符合stateless function components之條件, 可改用const來寫component

注意,使用const宣告的component裡面不可有state以及ref

從store 給到元件

1.

2.

3.

Last updated

Was this helpful?