原文:https://www.jianshu.com/p/81e9e9eaf8fa react
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對象
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對象。
const mapDispatchToProps = ( dispatch, ownProps ) => { return { onClick: () => { dispatch({ type: 'SET_VISIBILITY_FILTER', filter: ownProps.filter }); } }; }
從上面代碼能夠看到,mapDispatchToProps做爲函數,應該返回一個對象,該對象的每一個鍵值對都是一個映射,定義了 UI 組件的參數怎樣發出 Action。
const mapDispatchToProps = { onClick: (filter) => { type: 'SET_VISIBILITY_FILTER', filter: filter }; }
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 }