实现 React-redux(一) connect 和 mapStateToProps
1.结合 context 和 store
- import React, { Component } from 'react';
- import PropTypes from 'prop-types'
-  
- function createStore (reducer) {
-   let state = null
-   const listeners = []
-   const subscribe = (listener) => listeners.push(listener)
-   const getState = () => state
-   const dispatch = (action) => {
-     state = reducer(state, action)
-     listeners.forEach((listener) => listener())
-   }
-   dispatch({}) // 初始化 state
-   return { getState, dispatch, subscribe }
- }
-  
- const themeReducer = (state, action) => {
-   if (!state) return {
-     themeColor: 'red'
-   }
-   switch (action.type) {
-     case 'CHANGE_COLOR':
-       return { ...state, themeColor: action.themeColor }
-     default:
-       return state
-   }
- }
-  
- const store = createStore(themeReducer)
-  
- class Header extends Component {
-   static contextTypes = {
-     store: PropTypes.object
-   }
-  
-   constructor () {
-     super()
-     this.state = { themeColor: '' }
-   }
-  
-   componentWillMount () {
-     const { store } = this.context
-     this._updateThemeColor()
-     store.subscribe(() => this._updateThemeColor())
-   }
-  
-   _updateThemeColor () {
-     const { store } = this.context
-     const state = store.getState()
-     this.setState({ themeColor: state.themeColor })
-   }
-  
-   render () {
-     return (
-       <div>
-         <h1 style={{ color: this.state.themeColor }}></h1>
-         <ThemeSwitch />
-       </div>
-     )
-   }
- }
-  
- class ThemeSwitch extends Component {
-   static contextTypes = {
-     store: PropTypes.object
-   }
-  
-   // dispatch action 去改变颜色
-   handleSwitchColor (color) {
-     const { store } = this.context
-     store.dispatch({
-       type: 'CHANGE_COLOR',
-       themeColor: color
-     })
-   }
-  
-   render () {
-     return (
-       <div>
-         <button onClick={this.handleSwitchColor.bind(this, 'red')}>Red</button>
-         <button onClick={this.handleSwitchColor.bind(this, 'blue')}>Blue</button>
-       </div>
-     )
-   }
- }
-  
- class App extends Component {
-   static childContextTypes = {
-     store: PropTypes.object
-   }
-  
-   getChildContext () {
-     return { store }
-   }
-  
-   render() {
-     return (
-       <div>
-         <Header />
-       </div>
-     );
-   }
- }
-  
- export default App;
2.connect 和 mapStateToProps
App.js:
- import React, { Component } from 'react';
- import PropTypes from 'prop-types'
- import Header from './Header'
-  
- function createStore (reducer) {
-   let state = null
-   const listeners = []
-   const subscribe = (listener) => listeners.push(listener)
-   const getState = () => state
-   const dispatch = (action) => {
-     state = reducer(state, action)
-     listeners.forEach((listener) => listener())
-   }
-   dispatch({}) // 初始化 state
-   return { getState, dispatch, subscribe }
- }
-  
- const themeReducer = (state, action) => {
-   if (!state) return {
-     themeColor: 'red'
-   }
-   switch (action.type) {
-     case 'CHANGE_COLOR':
-       return { ...state, themeColor: action.themeColor }
-     default:
-       return state
-   }
- }
-  
- const store = createStore(themeReducer)
-  
- class App extends Component {
-   static childContextTypes = {
-     store: PropTypes.object
-   }
-  
-   getChildContext () {
-     return { store }
-   }
-  
-   render() {
-     return (
-       <div>
-         <Header />
-       </div>
-     );
-   }
- }
-  
- export default App;
Header.js:
- import React, { Component } from 'react';
- import PropTypes from 'prop-types'
- import { connect } from './react-redux'
- import ThemeSwitch from './ThemeSwitch'
-  
- class Header extends Component {
-   static propTypes = {
-     themeColor: PropTypes.string
-   }
-  
-   render () {
-     return (
-       <div>
-         <h1 style={{ color: this.props.themeColor }}></h1>
-         <ThemeSwitch/>
-       </div>
-     )
-   }
- }
-  
- const mapStateToProps = (state) => {
-   return {
-     themeColor: state.themeColor
-   }
- }
- Header = connect(mapStateToProps)(Header)
-  
- export default Header
react-redux.js:
- import React, { Component } from 'react'
- import PropTypes from 'prop-types'
-  
- export const connect = (mapStateToProps) => (WrappedComponent) => {
-   class Connect extends Component {
-     static contextTypes = {
-       store: PropTypes.object
-     }
-  
-     constructor () {
-       super()
-       this.state = { allProps: {} }
-     }
-  
-     componentWillMount () {
-       const { store } = this.context
-       this._updateProps()
-       store.subscribe(() => this._updateProps())
-     }
-  
-     _updateProps () {
-       const { store } = this.context
-       let stateProps = mapStateToProps(store.getState(), this.props) // 额外传入 props,让获取数据更加灵活方便
-       this.setState({
-         allProps: { // 整合普通的 props 和从 state 生成的 props
-           ...stateProps,
-           ...this.props
-         }
-       })
-     }
-  
-     render () {
-       return <WrappedComponent {...this.state.allProps} />
-     }
-   }
-  
-   return Connect
- }
-  
ThemeSwitch.js
- import React, { Component } from 'react';
- import PropTypes from 'prop-types'
-  
- class ThemeSwitch extends Component {
-   static contextTypes = {
-     store: PropTypes.object
-   }
-  
-   // dispatch action 去改变颜色
-   handleSwitchColor (color) {
-     const { store } = this.context
-     store.dispatch({
-       type: 'CHANGE_COLOR',
-       themeColor: color
-     })
-   }
-  
-   render () {
-     return (
-       <div>
-         <button onClick={this.handleSwitchColor.bind(this, 'red')}>Red</button>
-         <button onClick={this.handleSwitchColor.bind(this, 'blue')}>Blue</button>
-       </div>
-     )
-   }
- }
-  
- export default ThemeSwitch
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号