React Redux學習記錄

原文:https://www.jianshu.com/p/81e9e9eaf8fa react

connect()

React-Redux 提供connect方法,用於從 UI 組件生成容器組件。connect的意思,就是將這兩種組件連起來。redux

import { connect } from 'react-redux'
const VisibleTodoList = connect()(TodoList);

上面代碼中,TodoList是 UI 組件,VisibleTodoList就是由 React-Redux 經過connect方法自動生成的容器組件。ide

可是因爲沒有定義業務邏輯,上面這個 容器組件沒有實際yiyi,爲了實現業務邏輯,須要知足廈門的信息函數

1)輸入邏輯,外部的數據(state對象)轉換爲UI組件的參數this

2)輸出邏輯,用戶發出的動做怎麼變成Action對象,從UI組件傳出去spa

完整的connect方法code

import { connect } from 'react-redux'

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

 mapStateToProps負責輸入邏輯 state映射到UI組件的參數(props)component

   mapDispatchToProps 負責輸出邏輯,用戶對UI組件的操做映射成Action對象

mapStateToProps()  將state對象到Props對象的映射關係

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

上面代碼中,mapStateToProps是一個函數,它接受state做爲參數,返回一個對象。這個對象有一個todos屬性,表明 UI 組件的同名參數,後面的getVisibleTodos也是一個函數,能夠從state算出 todos 的值。blog

mapStateToProps會訂閱 Store,每當state更新的時候,就會自動執行,從新計算 UI 組件的參數,從而觸發 UI 組件的從新渲染。

mapStateToProps的第一個參數老是state對象,還可使用第二個參數,表明容器組件的props對象。

mapDispatchToProps()

它定義了哪些用戶的操做應該當作ACtion,傳給store,它能夠是一個函數,能夠是一個對象

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

  從上面代碼能夠看到,mapDispatchToProps做爲函數,應該返回一個對象,該對象的每一個鍵值對都是一個映射,定義了 UI 組件的參數怎樣發出 Action。

若是mapDispatchToProps是一個對象,它的每一個鍵名也是對應 UI 組件的同名參數,鍵值應該是一個函數,會被看成 Action creator ,返回的 Action 會由 Redux 自動發出。舉例來講,上面的mapDispatchToProps寫成對象就是下面這樣。


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

  

<Provider> 組件

connect方法生成容器組件之後,須要讓容器組件拿到state對象,才能生成 UI 組件的參數。

一種解決方法是將state對象做爲參數,傳入容器組件。可是,這樣作比較麻煩,尤爲是容器組件可能在很深的層級,一級級將state傳下去就很麻煩。

React-Redux 提供Provider組件,可讓容器組件拿到state。

import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'

let store = createStore(todoApp);

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

  上面代碼中,Provider在根組件外面包了一層,這樣一來,App的全部子組件就默認均可以拿到state了

class Provider extends Component {
  getChildContext() {
    return {
      store: this.props.store
    };
  }
  render() {
    return this.props.children;
  }
}

Provider.childContextTypes = {
  store: React.PropTypes.object
}

  上面代碼中,store放在了上下文對象context上面。而後,子組件就能夠從context拿到store,代碼大體以下。

class VisibleTodoList extends Component {
  componentDidMount() {
    const { store } = this.context;
    this.unsubscribe = store.subscribe(() =>
      this.forceUpdate()
    );
  }

  render() {
    const props = this.props;
    const { store } = this.context;
    const state = store.getState();
    // ...
  }
}

VisibleTodoList.contextTypes = {
  store: React.PropTypes.object
}
相關文章
相關標籤/搜索