1. 程式人生 > >React-Redux 總結

React-Redux 總結

類型 裏的 tex ide style urn 自帶 屬性 font

一、定義與功能

React-Redux 將所有組件分成兩大類:UI 組件(presentational component)和容器組件(container component)

1、UI 組件特征:

  • 只負責 UI 的呈現,不帶有任何業務邏輯
  • 沒有狀態(即不使用this.state這個變量)
  • 所有數據都由參數(this.props)提供
  • 不使用任何 Redux 的 API

2、容器組件特征:

  • 負責管理數據和業務邏輯,不負責 UI 的呈現
  • 帶有內部狀態
  • 使用 Redux 的 API

總結:

UI 組件負責 UI 的呈現,容器組件負責管理數據和邏輯。

React-Redux 規定,所有的 UI 組件都由用戶提供,容器組件則是由 React-Redux 自動生成。也就是說,用戶負責視覺層,狀態管理則是全部交給它。

二、使用與方法

1、connect方法 輸入UI組件, 輸出容器組件

React-Redux 提供connect方法,用於從 UI 組件生成容器組件。

// TodoList-> UI組件; VisibleTodoList -> 容器組件
// mapStatetoProps,mapDispatchToProps -> 它們定義了 UI 組件的業務邏輯。
// mapStatetoProps 可省略,若省略,UI 組件就不會訂閱Store,就是說 Store 的更新不會引起 UI 組件的更新
import { connect } from ‘react-redux‘
const VisibleTodoList 
= connect(mapStatetoProps, mapDispatchToProps)(TodoList);

(1) mapStateToProps(state [,props]) 負責輸入邏輯,即將state映射到 UI 組件的參數(props

state: 必選,state對象;props: 可選,代表容器組件的props對象
mapStateToProps會訂閱 Store,每當state更新的時候,就會自動執行,重新計算 UI 組件的參數(props),從而觸發 UI 組件的重新渲染。

// map Redux state to component props (把 Redux state 映射到 component props)
const mapStatetoProps = (state) => { return {num: state} } // 使用ownProps作為參數後,若容器組件的參數(ownProps)發生變化,也會引發 UI 組件重新渲染 const mapStateToProps = (state, ownProps) => { return { active: ownProps.filter === state.visibilityFilter } }

(2) mapDispatchToProps 負責輸出邏輯,即將用戶對 UI 組件的操作映射成 Action。

// map Redux actions to component props (把 Redux actions 映射到 component props)
const mapDispatchToProps = dispatch => {
  return {
    onIncreaseClick: () => dispatch(increaseAction)
  };
}

mapDispatchToProps 分為兩種類型:函數和對象

mapDispatchToProps是一個函數,會得到dispatchownProps(容器組件的props對象)兩個參數。

mapDispatchToProps作為函數,應該返回一個對象,該對象的每個鍵值對都是一個映射,定義了 UI 組件的參數怎樣發出 Action

const mapDispatchToProps = (
  dispatch,
  ownProps
) => {
  return {
    onClick: () => {
      dispatch({
        type: ‘SET_VISIBILITY_FILTER‘,
        filter: ownProps.filter
      });
    }
  };
}

mapDispatchToProps是一個對象,鍵名是對應 UI 組件的同名參數,鍵值應該是一個函數,會被當作 Action creator ,返回的 Action 會由 Redux 自動發出

const mapDispatchToProps = {
  onClick: (filter) => {
    type: ‘SET_VISIBILITY_FILTER‘,
    filter: filter
  };
}

三、原理與流程

為了讓子組件能夠獲得context屬性,React強制要求根組件(此處為Provider組件)提供getChildContext實例方法,以及類屬性childContextTypes。而子組件想要獲取context,也必須定義類級別的Counter. contextTypes屬性。定義是雙向的,如果缺少了任何一塊,子組件都獲取不到context屬性。

我認為父組件的那塊定義是在Provider的代碼中實現的,而子組件的那部分是在connect方法中實現的。

因此connect方法為Counter組件添加的context屬性實質上是由Provider傳下來的,這樣在mapStatesToProps方法裏的state參數實質上就是this.context.store.getState()方法獲得的。

頁面首次加載以及之後有互動行為之後整個邏輯的流程:

(1)頁面首次加載時,store裏的初始state獲取過程:
createStore(reducers,defaultParams)的調用,其中reducers可以使一個reducer,也可是redux.combineReducers過的reducer的集合。

createStore方法會對每個reducer去dispatch一個action.type=@@redux/INIT類型的action,而這個action一般在reducer的代碼裏不會被handle,直接掉入default塊,於是就返回了state的初始狀態。

然後一般就會ReactDom.render()將應用渲染出來,每個子組件的容器組件通過傳入this.context.store.getState()方法獲得的state對象, 以及容器組件上自帶的ownProps給mapStatesToProperties方法,來構建props,最後將props應用到子組件的UI組件上。

(2)互動行為之後整個邏輯:

當在子組件上發生交互行為,如click時,mapDispatchToProps會定義click觸發時應該dispatch哪一個action的映射。
然後store接收到這個action後會進行reduce,得到最新的state,然後再調用所有的子組件的mapStatesToProps方法生成新的props。
最後對Provider進行重新渲染。當然上面的事件計算出來的很多state可能都不會發生變化,所以diff算法不會去修改這些沒有發生變化的組件,因此性能也比較好。

 

React-Redux 總結