原文鏈接
React認為每個組件都是一個個有限狀態機,狀態與UI是一一對應的。我們只需管理好APP的state就能控制UI的顯示,我們可以在每個component類中來通過this.state和this.setState來管理組件的state,但是如果APP交互比較多比較復雜,或者說該組件的某一狀態需要和其他組件共享的話,這種方式就有點復雜了。   有沒有一種能統一管理APP狀態的框架呢,這時候Redux就在我們的期盼中駕著七彩祥云降臨人間了,她是一個用于統一管理APP 所有的state的一個的js框架,她不建議我們在component中直接操作state,而是交給redux的store中進行處理。后來又發現redux使用著也是不太方便啊,每次dispatch(action)的時候都需要store對象,最后redux的作者又專門為react native量身訂做了一個react-redux。
(1)Web 應用是一個狀態機,視圖與狀態是一一對應的。 (2)所有的狀態,保存在一個對象里面,由其統一管理。 (3)狀態在組件中是‘只讀’的,要交給redux處理
有圖有真相,先來一張redux數據流圖,讓你有一個整體的把握 
一般是不允許用戶直接操作類的state,而是通過觸發消息來執行對應的操作來產生一個新的state,用戶或后臺服務器可以通過store.dispatch(action)來向store發送一個消息(消息至少一個標識該消息的字段type,還可以添加其他字段用于數據傳送),store會在內部根據消息的類型type去reducer中執行相應的處理,這個消息我們就叫他為Action,Action本質上是一個javaScript對象。
實際編碼中一般會把整個應用的消息類型統一放在一個文件ActionTypes.js中
export const ADD_TODO = 'ADD_TODO'Action的結構如下,各個字段的key的名字可以隨意命名,但是類型的key一般都是type,數據類型最好為字符串
{ type: ADD_TODO, text: 'Build my first Redux app'}隨著程序越來越大,你會發現一個組件中的action太多太亂了,所以我們也會把action按業務分類放在各個指定的文件中,但是又有一個問題,若果每個action的字段都有五六個,我們在如下寫法豈不是太亂了
store.dispatch({ type: ADD_TODO, text: 'Build my first Redux app'})于是乎我們就想起來可以將action對象封裝在函數中,這個函數返回一個action對象,這個返回一個action對象的函數我們就稱之為ActionCreator,如下所示
export let todo = ()=> { return { type: ADD_TODO, text: 'Build my first Redux app' }}我們直接store.dispatch(todo)就好了,看著是不是整潔多了啊
它是一個純函數,要求有相同的輸入(參數)就一定會有相同的輸出,它會根據當前的state和action來進行邏輯處理返回一個新的state 參數一:當前的state對象 參數二:action對象 返回值:產生一個新的state對象
import { VisibilityFilters } from './actions'//初始stateconst initialState = { visibilityFilter: VisibilityFilters.SHOW_ALL, todos: []};function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) default: return state }}注意:reducer函數中一定不要去修改state,而是用Object.assign()函數生成一個新的state對象,如上所示
combineReducers:隨著應用變得復雜,把APP的所有狀態都放在一個reducer中處理會造成reducer函數非常龐大,因此需要對 reducer 函數 進行拆分,拆分后的每一個子reducer獨立負責管理 APP state 的一部分。combineReducers 輔助函數的作用是,把多個不同子reducer 函數合并成一個最終的根reducer ,最后將根 reducer 作為createStore的參數就可以創建store對象了。合并后的 reducer 可以調用各個子 reducer,并把它們的結果合并成一個 state 對象。state 對象的結構由傳入的多個 reducer 的 key 決定。
最終,state 對象的結構會是這樣的:
{ reducer1: ... reducer2: ...}使用方法如下所示
import { combineReducers } from 'redux';import Strolling from './strollingReducer';import Foods from './foodsReducer';import FoodsList from './foodsListReducer';import FoodCompare from './foodCompareReducer';import FoodInfo from './foodInfoReducer';import Search from './searchReducer';import User from './userReducer';export default rootReducer = combineReducers({ Strolling, Foods, FoodsList, FoodCompare, FoodInfo, Search, User,})// export default rootReducer = combineReducers({// Strolling:Strolling,// Foods:Foods, // FoodsList:FoodsList,// FoodCompare:FoodCompare,// FoodInfo:FoodInfo,// Search:Search,// User:User,// })// export default function rootReducer(state = {},action){// return{// Strolling: Strolling(state.Strolling,action),// Foods:Foods(state.Foods,action),// FoodsList:FoodsList(state.FoodsList,action),// FoodCompare:FoodCompare(state.FoodCompare,action),// FoodInfo:FoodInfo(state.FoodInfo,action),// Search:Search(state.Search,action),// User:User(state.User,action)// }// }//以上三種方式是等價的,key可以設置也可以省略一個應用只有一個store,store 就是用來維持應用所有的 state 樹 的一個對象。 改變 store 內 state 的惟一途徑是對它 dispatch 一個 action,它有三個函數 * getState()     返回應用當前的 state 樹。 * dispatch(action)     分發 action。這是觸發 state 變化的惟一途徑。     會使用當前 getState() 的結果和傳入的 action 以同步方式的調用 store 的 reduce 函數。返回值會被作為下一個 state。從現在開始,這就成為了 getState() 的返回值,同時變化監聽器(change listener)會被觸發。 * subscribe(listener)     當state樹發生變化的時候store會調用subscribe函數,我們可以傳一個我們訂制的函數作為參數來進行處理     參數:一個函數     返回值:返回一個解綁定函數     Javascript     //添加監聽     let unsubscribe = store.subscribe(handleChange)     //解除監聽     unsubscribe()  *  replaceReducer(nextReducer)     替換 store 當前用來計算 state 的 reducer。     這是一個高級 API。只有在你需要實現代碼分隔,而且需要立即加載一些 reducer 的時候才可能會用到它。在實現 Redux 熱加載機制的時候也可能會用到。
react-redux是redux作者專門為react native訂制的,這樣使用起來更方便,我們只需在我們的組件中通過屬性PRops獲取dispatch方法,就可以直接向store發送一個action,而不需要再獲取store對象,通過store對象的dispatch方法發送。 react-redux有兩寶,provider和connect,下面詳細介紹一下。
有一個store屬性,我們要將應用的根標簽放到Provider標簽中,這樣應用的所有標簽就可以通過context來獲取store對象了,但是我們一般不會通過此法來獲取store對象,Provider是為了給connect函數使用的,這樣才能從connect函數獲取到state和dispatch了。
參數一:[mapStateToProps(state, [ownProps]): stateProps] (Function)
如果定義該參數,組件將會監聽 Redux store 的變化。任何時候,只要 Redux store 發生改變,mapStateToProps 函數就會被調用。該回調函數必須返回一個純對象,這個對象會與組件的 props 合并。如果你省略了這個參數,你的組件將不會監聽 Redux store。如果指定了該回調函數中的第二個參數 ownProps,則該參數的值為傳遞到組件的 props,而且只要組件接收到新的 props,mapStateToProps 也會被調用(例如,當 props 接收到來自父組件一個小小的改動,那么你所使用的 ownProps 參數,mapStateToProps 都會被重新計算)。
參數二:[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function):
如果傳遞的是一個對象,那么每個定義在該對象的函數都將被當作 Redux action creator,而且這個對象會與 Redux store 綁定在一起,其中所定義的方法名將作為屬性名,合并到組件的 props 中。如果傳遞的是一個函數,該函數將接收一個 dispatch 函數,然后由你來決定如何返回一個對象,這個對象通過 dispatch 函數與 action creator 以某種方式綁定在一起(提示:你也許會用到 Redux 的輔助函數 bindActionCreators())。如果你省略這個 mapDispatchToProps 參數,默認情況下,dispatch 會注入到你的組件 props 中。如果指定了該回調函數中第二個參數 ownProps,該參數的值為傳遞到組件的 props,而且只要組件接收到新 props,mapDispatchToProps 也會被調用。
參數三:[mergeProps(stateProps, dispatchProps, ownProps): props] (Function)
如果指定了這個參數,mapStateToProps() 與 mapDispatchToProps() 的執行結果和組件自身的 props 將傳入到這個回調函數中。該回調函數返回的對象將作為 props 傳遞到被包裝的組件中。你也許可以用這個回調函數,根據組件的 props 來篩選部分的 state 數據,或者把 props 中的某個特定變量與 action creator 綁定在一起。如果你省略這個參數,默認情況下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的結果。 [options] (Object) 如果指定這個參數,可以定制 connector 的行為。
參數四:[options] (Object) 如果指定這個參數,可以定制 connector 的行為。
[pure = true] (Boolean): 如果為 true,connector 將執行 shouldComponentUpdate 并且淺對比 mergeProps 的結果,避免不必要的更新,前提是當前組件是一個“純”組件,它不依賴于任何的輸入或 state 而只依賴于 props 和 Redux store 的 state。默認值為 true。 [withRef = false] (Boolean): 如果為 true,connector 會保存一個對被包裝組件實例的引用,該引用通過 getWrappedInstance() 方法獲得。默認值為 false。

redux是不允許用戶來管理state的,而是交給redux管理,redux中有一個全局唯一的store來存放和管理state樹。用戶通過界面(或者網絡請求等)來dispatch一個action,store接收到action后根據action的類型找到reducer中對應的邏輯進行數據處理,reducer處理后會返回一個新的state對象,然后程序根據store.subscribe訂閱監聽state的變化進行界面更新。
為啥這個圖又出現了呢,因為只想讓你多看她一眼 O(∩_∩)O哈哈~

react-redux是redux的作者為react native封裝的一個庫,原理和redux一樣,只是使用起來更方便了。
React 實踐心得:react-redux 之 connect 方法詳解 Redux 入門教程(一):基本用法 redux中文文檔
注:圖片來源于互聯網
新聞熱點
疑難解答