实现 React-redux(二) mapDispatchToProps

 

App.js:

  1. import React, { Component } from 'react';
  2. import PropTypes from 'prop-types'
  3. import Header from './Header'
  4. function createStore (reducer) {
  5. let state = null
  6. const listeners = []
  7. const subscribe = (listener) => listeners.push(listener)
  8. const getState = () => state
  9. const dispatch = (action) => {
  10. state = reducer(state, action)
  11. listeners.forEach((listener) => listener())
  12. }
  13. dispatch({}) // 初始化 state
  14. return { getState, dispatch, subscribe }
  15. }
  16. const themeReducer = (state, action) => {
  17. if (!state) return {
  18. themeColor: 'red'
  19. }
  20. switch (action.type) {
  21. case 'CHANGE_COLOR':
  22. return { ...state, themeColor: action.themeColor }
  23. default:
  24. return state
  25. }
  26. }
  27. const store = createStore(themeReducer)
  28. class App extends Component {
  29. static childContextTypes = {
  30. store: PropTypes.object
  31. }
  32. getChildContext () {
  33. return { store }
  34. }
  35. render() {
  36. return (
  37. <div>
  38. <Header />
  39. </div>
  40. );
  41. }
  42. }
  43. export default App;

Header.js:

  1. import React, { Component } from 'react';
  2. import PropTypes from 'prop-types'
  3. import { connect } from './react-redux'
  4. import ThemeSwitch from './ThemeSwitch'
  5. class Header extends Component {
  6. static propTypes = {
  7. themeColor: PropTypes.string
  8. }
  9. render () {
  10. return (
  11. <div>
  12. <h1 style={{ color: this.props.themeColor }}></h1>
  13. <ThemeSwitch/>
  14. </div>
  15. )
  16. }
  17. }
  18. const mapStateToProps = (state) => {
  19. return {
  20. themeColor: state.themeColor
  21. }
  22. }
  23. Header = connect(mapStateToProps, null)(Header)
  24. export default Header

react-redux.js:

  1. import React, { Component } from 'react'
  2. import PropTypes from 'prop-types'
  3. export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
  4. class Connect extends Component {
  5. static contextTypes = {
  6. store: PropTypes.object
  7. }
  8. constructor () {
  9. super()
  10. this.state = {
  11. allProps: {}
  12. }
  13. }
  14. componentWillMount () {
  15. const { store } = this.context
  16. this._updateProps()
  17. store.subscribe(() => this._updateProps())
  18. }
  19. _updateProps () {
  20. const { store } = this.context
  21. let stateProps = mapStateToProps
  22. ? mapStateToProps(store.getState(), this.props)
  23. : {} // 防止 mapStateToProps 没有传入
  24. let dispatchProps = mapDispatchToProps
  25. ? mapDispatchToProps(store.dispatch, this.props)
  26. : {} // 防止 mapDispatchToProps 没有传入
  27. this.setState({
  28. allProps: {
  29. ...stateProps,
  30. ...dispatchProps,
  31. ...this.props
  32. }
  33. })
  34. }
  35. render () {
  36. return <WrappedComponent {...this.state.allProps} />
  37. }
  38. }
  39. return Connect
  40. }

ThemeSwitch.js:

  1. import React, { Component } from 'react';
  2. import PropTypes from 'prop-types'
  3. import { connect } from './react-redux'
  4. class ThemeSwitch extends Component {
  5. static contextTypes = {
  6. store: PropTypes.object
  7. }
  8. handleSwitchColor (color) {
  9. if (this.props.onSwitchColor) {
  10. this.props.onSwitchColor(color)
  11. }
  12. }
  13. render () {
  14. return (
  15. <div>
  16. <button onClick={this.handleSwitchColor.bind(this, 'red')}>Red</button>
  17. <button onClick={this.handleSwitchColor.bind(this, 'blue')}>Blue</button>
  18. </div>
  19. )
  20. }
  21. }
  22. const mapDispatchToProps = (dispatch) => {
  23. return {
  24. onSwitchColor: (color) => {
  25. dispatch({ type: 'CHANGE_COLOR', themeColor: color })
  26. }
  27. }
  28. }
  29. ThemeSwitch = connect(null, mapDispatchToProps)(ThemeSwitch)
  30. export default ThemeSwitch

 

posted @ 2024-03-18 09:39  mounter爱学习  阅读(13)  评论(0编辑  收藏  举报