Redux story-1:who creates it?

前言

 這是一個系列文章,旨在分享在react及相關技術棧實踐過程當中的我的感悟,心得。若是有很差的地方,歡迎各位批評指正。react

 因爲對react自己還未深刻了解,今天咱們先來談一談redux相關的問題。webpack

Who creates it?

Dan Abramovredux的做者,同時,他也是Create React App, React Hot Loader做者。固然1年前,他也因爲redux及相關的開源貢獻加入了facebook(他大二就輟學了,以前還當過.net工程師)。git

 在我最初瞭解到他的時候,我以爲他很是有禮貌。同時,也爲了更多的瞭解redux,我計劃開始閱讀他的每一條tweet,原先計劃的是從15年7月開始,後來由於進展緩慢,並且react版本也已經發生很大變化了,因而便從16年1月1日開始閱讀,目前記錄到7月15日了。事實也證實,在這個過程當中,的的確確學習到了不少東西。包括redux的文檔及redux-links的做者Mark Erikson,以及國外不少寫過redux系列的朋友們。程序員

 若是你有興趣的話,能夠看看我摘錄的一些片斷。其中除了知識性的內容外,還有一些關於它本身生活,經歷,學習方法,如何面對JS疲勞等等的摘錄。也讓我漸漸的瞭解到了國外的程序員們的一些觀點,興趣,梗等等。github

正文

 好了,暫時先介紹到這裏了。切回redux自己,下面是學習源碼過程當中本身的一些體會。web

createStore

createStore的第3個參數爲enhancer,若是enhancer有多個,那麼應該使用compose的方式組合多個enhancer數據庫

 且每一個enhancer的模板爲export default createStore => (reducer, preloadedState, enhancer) => {...}redux

 由於在createStore中執行了:return enhancer(createStore)(reducer, preloadedState)性能優化

 另外,上面的提到的形如(reducer, preloadedState, enhancer) => {...} 這個樣子的其實均可以叫作createStore網絡

 這也是社區有那麼多enhancer的緣由,他們能夠造成一個enhancer鏈,我調用你的createStore,而後返回個人createStore供下一級調用

 因此在本身的createStore的函數體中常常能看到諸如var store = createStore(reducer, preloadedState, enhancer);這樣的用法,目的就是讓本身這一級以前的enhancer產生一個store出來,而以前的enhancer裏的createStore又會調用以前的,到最盡頭,就是redux自己的createStore

applyMiddleware

applyMiddleware的目的是返回一個enhancer,這個enhancer存儲了1個或者多箇中間件,中間件在上一級的dispatch方法的基礎上增添本身的邏輯,而後返回本身的dispatch方法

 對於中間件而言,中間件的模板爲:export default store => next => action => {...}。有的地方也寫成export default _ref => next => action => {...}或者export default ({getState, dispatch}) => next => action => {...},看本身喜愛了

 實際的調用順序以下(定義在reduxapplyMiddleware.js中):

1. middleware(middlewareAPI);
/*
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);

    第1步即爲第1次執行中間件,用redux本身的dipatch初始化各個中間件裏的dispatch(也就是中間件的next參數)和getState。
    從而確保至少redux自己可以正常工做,中間件的store或者_ref即爲這裏的middlewareAPI
* */

2. dispatch = compose(...chain)(store.dispatch);
/*
    第2步即爲第2次執行中間件
    即用compose的形式鏈式調用第1步返回的中間件集合,若是中間件是定義在applyMiddleware的最後一個
    那麼中間件裏的next爲store.dispatch,不然next爲上一個中間件返回的結果,能夠理解爲上一個中間件
    返回的是封裝了dispatch的本身的dispatch,這裏的原理其實和enhancer如出一轍

    enhancer的目的是封裝屢次createStore並用compose的方式進行調用
    middleware的目的是封裝屢次dispatch並用compose的方式進行調用
* */

總結:
/*
    因此最後在redux的createStore.js中return的enhancer(createStore)(reducer, preloadedState)的結果就是一個加強
    版的store,而這個加強版的store中存放的是加強版的dispatch
* */

/* ××××××××××××××××關於combineReducers×××××××××××××××
*   從執行上來講,combineReducers實際上最後就是變成對reducers進行深度優先遍歷並執行的過程
*   從結構上來講,combineReducers決定了咱們的state狀態樹的最終結構或者說形狀,他是呈一個樹型結構的
*   combineReducers(reducerA, reducerB),reducerA裏面嵌套combineReducers(reducerA-child1, reducerA-child2)
*   實際上對應狀態樹而已就是第一層有兩個節點A,B,而A節點下面有兩個子節點A-child1,A-child2
*
*   因此在最初設計的時候,咱們要設想咱們最終的狀態樹的樣子,而後合理劃分reducer,就像設計數據庫的表結構同樣。
    固然這是比較歸納的說法,事實上reducer的設計或者說state的劃分有太多太多值得研究的東西,這個咱們之後再談了。
* */

bindActionCreator

bindActionCreator實際就是給actionCreator外層再添加了一層函數,而這層函數存放了對dispatch的引用

function bindActionCreator(actionCreator, dispatch) {
  return (...args) => dispatch(actionCreator(...args))
}

因此咱們能夠通常在組件裏直接調用bindActionCreator返回的actionCreator,即this.props.loadSomething(...)。而不用寫成dispatch(actionCreator(...args)),實際上他們是等價的

connect

 既然提到了redux,因爲目前我是採用react進行開發,因此不得不提到相關的react-redux。其中最重要的莫屬於connect這個函數了。

 傳入connect的組件在掛載到頁面上後會調用store.subscribe進行訂閱,訂閱的目的是咱們調用dispatch的時候,代表咱們的狀態樹即將發生變化,這個時候咱們但願咱們的組件對應發生變化,而組件變化的惟一方式就是setState

 訂閱就是告訴redux,這個組件是依賴於狀態樹的某部分工做的,因此當你變化的時候,記得獲取最新的state,而後通知我,至於我如何響應,那就是我本身的事了,你只管通知我狀態樹發生了變化並把它傳給我就好了。值得一提的是,connect內部進行了大量的性能優化,避免沒必要要的渲染,關於此以及mapStateToPropsmapDispathToProps,咱們放到之後再談。

結語

 篇幅有限,這一篇文章暫時就先這樣啦,更多的內容,我想放在下一篇來分享,同時本身也在不斷學習,但願能理解得更好。

 值得一提的是,咱們也許會認爲咱們瞭解到的redux,mobx,rxjs等等徹底不一樣理念的庫,他們的做者也許也是"極端"的,是排斥他人及理念的。實際上,這是不正確的,早在16年5月,Dan就和mobx的做者在twitter上有過互動,他們達成了共識,那就是和對方一塊兒合做,一塊兒推進自身以及react的發展。

 對於redux-thunk,文檔中也許會首先建議使用這個簡單的庫來處理異步相關的問題。對於複雜的應用,他們也推薦使用redux-saga這樣的庫去重構本身的代碼。在twitter上,Dan也屢次提到過庫的應用場景的問題,建議你們用以前先了解本身爲何要使用,它解決了哪些痛點,而後再去使用。甚至特地提過issue,來了解react-router-redux的做用。

 除此以外,也提到在時間充裕的狀況下,學習react,應該先從自己入手,ES6,webpack,jsx,redux等等和react自己都是沒有直接聯繫的,在學習完react以後,咱們知道了他自己的哪些不足,哪些地方須要增強,哪些地方須要引入第三方庫去解決,解決的是哪些痛點,咱們再去了解這些工具,才能真正體會到他們的威力。

 說到這裏,稍微有一點遠了,不過我以爲仍是有必要說起一下。那就是,咱們身處一個浮躁的社會,不管是在現實中對待朋友,親人,陌生人,因爲學習,工做,生活的壓力,周遭的浮躁氛圍的影響,多多少少也會讓本身帶着些許暴戾之氣。在網絡上,因爲約束的放寬,咱們也許更會將壓抑的情感釋放給廣袤的網絡世界,在微博,貼吧,知乎上,咱們或多或少書寫着,察覺着這樣的行爲。

 可是,做爲一名程序猿,我仍是期待可以看到咱們這個圈子更多的將時間,精力,努力花費在對現有技術的改進,對未知世界的探索,追尋程序,庫,框架,思想的本質,結交志同道合的朋友,一塊兒交流,分享,思考對技術的見解。而不是捲入無休止的撕逼,用了某某而產生的優越,甚至借貶低他人來擡高本身。

 咱們能夠理解一時的憤懣之情,由於咱們大多,真是隻是普普統統的社會人,喜怒哀樂再日常不過。但若咱們一直保持這種狀態,永遠在上面這些場景都留下對人不對事的話語,譏諷,甚至謾罵。但願你們能爲咱們的後代想一想。

相關文章
相關標籤/搜索