react-redux淺析

這篇文章主要來看下兩個用的最多的函數背後的原理,connect和combineReducers

react-redux的connect函數簡化版源碼解釋

// connect() 是一個往組件注入redux相關屬性的函數
// 你能夠注入數據和(經過分發action去改變數據的)回調函數
function connect(mapStateToProps, mapDispatchToProps) {
  // 經過這一層閉包,它實現了讓咱們在最後一步注入組件的能力,這樣的設計讓你們能夠把它當成decorator使用
  return function (WrappedComponent) {
    // 返回一個組件,這個結構即react提過的HOC
    return class extends React.Component {
      render() {
        return (
          <WrappedComponent
            {/* 父組件傳入的props  */}
            {...this.props}
            {/* Redux store經過map*函數計算出的props */}
            {...mapStateToProps(store.getState(), this.props)}
            {...mapDispatchToProps(store.dispatch, this.props)}
          />
        )
      }
      
      componentDidMount() {
        // 一旦組件鏈接上store,它會幫你subscribe,因此你的組件不會錯過任何狀態更新
        this.unsubscribe = store.subscribe(this.handleChange.bind(this))
      }
      
      componentWillUnmount() {
        // 卸載時幫你註銷訂閱
        this.unsubscribe()
      }
    
      handleChange() {
        // store更新以後從新繪製
        this.forceUpdate()
      }
    }
  }
}

// 這不是真正源碼,而是一個簡化版的模型.
// 它跳過了‘store從哪來’的問題 (答案: <Provider> 把它放進了React上下文)
// 也跳過了性能優化的問題 (真正的connect()確保了不會作無心義的重繪).

// connect() 的目的就是讓你沒必要考慮訂閱store或性能優化,而是如何獲得你想要的狀態state

// 使用例子
const ConnectedCounter = connect(
  // 回調函數拿到state返回prop
  state => ({
    value: state.counter,
  }),
  // 回調函數拿到dispatch函數,返回包含dispatch的回調函數
  dispatch => ({
    onIncrement() {
      dispatch({ type: 'INCREMENT' })
    }
  })
)(Counter)複製代碼


Redux的combineReducers函數

reducers太多的時候,咱們可能想把他們按照相關性分開,便於管理,在最後用combineReducers在合在一塊兒就行。看下面沒用這個函數的例子javascript

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

function todoApp(state = {}, action) {
  return {
    visibilityFilter: visibilityFilter(state.visibilityFilter, action),
    todos: todos(state.todos, action)
  }
}複製代碼

其實真相已經不言而喻了,最後的todoApp就等價於combineReducersjava

import { combineReducers } from 'redux'

const todoApp = combineReducers({
  visibilityFilter,
  todos
})

export default todoApp複製代碼

引用

gist.github.com/gaearon/1d1…
react

redux.js.org/basics/redu…
git

相關文章
相關標籤/搜索