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?