項目驅動是學習框架很是高效的一種方式。
學習 redux 全家桶推薦 react-douban:一個 React + Redux + React-Router 完整項目javascript
該筆記主要是下面三部分:前端
Redux是一個管理狀態容器,將整個前端應用的狀態都統一到一個地方管理。經過單一數據流操做,來實現單一狀態。使得前端應用更加方便的管理狀態。java
整個state就是一個object,能夠將store理解爲前端的數據庫,沒有setter,不能直接更改。
若是要更改state,則須要dispatch an action。而 action 則是一個對象,用於描述提交了什麼操做,而不涉及對 state 具體的操做。
強制使用action來改變每一次的state,可讓咱們更加容易追蹤到每次state的變化。
而 Reducer 則是用來將 Action 和 State 串起來的一個函數。用於具體處理對 state 的改變。react
以上的過程差很少就是整個 Redux 的思想。git
在你的應用中state存儲在一個 object tree,並且這個object tree 在該應用中是惟一一個的。
將全部state存在於應用中惟一一個object tree 帶來的好處是:能夠實現開發環境下的保存狀態的歷史狀態,實現Undo/Redo等功能。github
改變 state 的惟一方式就是觸發一個 action(action 是一個用於描述發生了什麼的對象)數據庫
爲了描述action 如何具體改變 state tree,你須要編寫reducers。Reducer 只是一些純函數。
Reducer 接收 state 和 action 做爲參數,並返回新的 state。json
Store就是保存數據的地方,能夠看出是一個容器,整個應用就只能有一個store。Redux提供createStore()
函數來生成storeredux
import {createStore} from 'redux'
const store = createStore(app);複製代碼
store 某個節點對應的數據集合就是state。能夠經過store.getState()
得到。
Redux 規定,一個state對應一個View。State相同,則View相同。api
State 的變化會致使 View 的變化。可是用戶接觸不到State,只能接觸到View。因此State的變化必須是View致使的。Action就是View發出的通知,表示State要發生改變了。
Action是一個對象,其中type屬性是必須的,表示Action的名稱。其餘屬性隨意。
用於生成Action 的函數。
store.dispatch()
是View發出Actiion 的惟一辦法。
import {createStore} from 'redux'
const store = createStore(fn);
store.dispatch(addTodo(text))複製代碼
Store 收到Action以後,必須給出一個新的State,這樣才能使View發生變化。這種State的計算過程叫作Reducer。
Reducer 是一個函數,它接受Action和當前的state做爲參數,返回一個新的state。
整個應用的初始狀態,能夠做爲state的默認值。
Reducer還能夠進行拆分,而後經過combineReducers
方法,結合成一個大的Reducer。
首先用戶發出Action。
store.dispatch(action)複製代碼
而後store自動調用Reducer,而且傳入兩個參數:當前的state 和 收到的Action. Reducer 會返回新的state。
let nextState = reducer(previousState, action)複製代碼
State一旦變化,Store就會調用監聽函數。Listener能夠經過store.getState()
獲得當前狀態。
Redux解決了同步狀態更新的問題,可是異步操做卻沒有解決。
若是要 使Reducer在異步操做結束後自動執行,必須使用中間件。
createStore()
方法包含了參數applyMiddleware()
,
它是Redux的原生方法,做用是 將全部的中間件組成一個數組,依次執行
異步操做須要發出三種Action
因此流程也很清楚:
解決方案:
寫出一個返回函數的 Action Creator,而後使用redux-thunk
中間件改造store.dispatch
。
import {createStore, applyMiddleware} from 'redux'
import thunk from 'react-thunk'
const store = createStore(
rootReducer,
applyMiddleware(thunk)
)
export function fetchPost() {
}
export function requestPost(){}
export function receivePost(){}
export function handleError(err) {
}
export function requstAync() {
return function(dispatch){
// 請求發起時 dispatch action
dispatch(requestPost())
// 這裏的fetchPost 是一個Promise
return fetchPost()
.then(response => response.json())
.then(json =>
// 請求成功時 dispatch action
dispatch(receivePost())
)
.catch(err =>
// 請求錯誤時 dispatch action
dispatch(handleError(err))
)
}
}複製代碼
React-Redux將組件分爲兩種:
若是遇到一個組件既有UI和業務邏輯時,須要拆分紅下面的結構:
外面是一個容器組件,裏面包含若干個UI組件。容器組件負責與外部的通訊、傳遞數據給UI組件。
UI組件則負責頁面顯示。
用於從UI組件生成容器組件。能夠這麼來理解 connect 的做用。
connect 就是將 state 上的 props(屬性)和 方法(dispatch)添加到對應的 UI組件上。
import {connect} from 'react-redux'
import {TodoList} from './TodoList'
export default connect()(TodoList)複製代碼
上面的代碼就將UI組件 TodoList 轉換爲一個容器組件。
每一個容器組件須要定義兩方面的信息:
完整的connect
方法的API以下:
import {connect} from 'react-redux'
import {TodoList} from './TodoList'
function mapStateToProps(state){
return{
// do something
}
}
function mapDispatchToProps(dispatch){
return{
// do something
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)複製代碼