看这里之前,需要了解redux最简易的版本实现代码的逻辑,这里我们粘贴一下,详细内容请移步redux原理 + 简易实现 —- 基础实现篇
    **

    1. function createStore (state, stateChanger) {
    2. const listeners = []
    3. const subscribe = (listener) => listeners.push(listener)
    4. const getState = () => state
    5. const dispatch = (action) => {
    6. state = stateChanger(state, action) // 覆盖原对象
    7. listeners.forEach((listener) => listener())
    8. }
    9. dispatch({})
    10. return { getState, dispatch, subscribe }
    11. }

    结合我们要演示的reducer,代码如下

    1. import React, { Component } from 'react'
    2. import PropTypes from 'prop-types'
    3. import ReactDOM from 'react-dom'
    4. import Header from './Header'
    5. import Content from './Content'
    6. import './index.css'
    7. function createStore (reducer) {
    8. let state = null
    9. const listeners = []
    10. const subscribe = (listener) => listeners.push(listener)
    11. const getState = () => state
    12. const dispatch = (action) => {
    13. state = reducer(state, action)
    14. listeners.forEach((listener) => listener())
    15. }
    16. dispatch({}) // 初始化 state
    17. return { getState, dispatch, subscribe }
    18. }
    19. const themeReducer = (state, action) => {
    20. if (!state) return {
    21. themeColor: 'red'
    22. }
    23. switch (action.type) {
    24. case 'CHANGE_COLOR':
    25. return { ...state, themeColor: action.themeColor }
    26. default:
    27. return state
    28. }
    29. }
    30. const store = createStore(themeReducer)
    31. ...

    定义了一个主题redecer,并设置了对其操作是改变颜色

    其实Provider逻辑很简单,就是把react的context传递给下面,也就是传递给connect组件,所以我们用一个HOC的方式来写

    1. import React, { Component } from 'react'
    2. export const ThemeContext = React.createContext(props.store)
    3. export class Provider extends Component {
    4. constructor(props){
    5. super(props)
    6. }
    7. render () {
    8. return (
    9. <ThemeContext.Provider>{this.props.children}</ThemeContext.Provider>
    10. )
    11. }
    12. }

    接着,我们来看一下如何使用它

    1. ...
    2. // 头部引入 Provider
    3. import { Provider } from './react-redux'
    4. ...
    5. // 删除 Index 里面所有关于 context 的代码
    6. class Index extends Component {
    7. render () {
    8. return (
    9. <div>
    10. <Header />
    11. <Content />
    12. </div>
    13. )
    14. }
    15. }
    16. // 把 Provider 作为组件树的根节点
    17. // 这里的store是指redux的createStore创建出来的store
    18. ReactDOM.render(
    19. <Provider store={store}>
    20. <Index />
    21. </Provider>,
    22. document.getElementById('root')
    23. )

    我们来看看Provider底下的组件,如果没有connect组件的话,该如何调用呢

    1. import { ThemeContext } from './Provider'
    2. class Index extends Component {
    3. static contextType = ThemeContext;
    4. constructor () {
    5. super()
    6. this.state = { themeColor: '' }
    7. }
    8. componentWillMount () {
    9. const { store } = this.context
    10. this._updateThemeColor()
    11. store.subscribe(() => this._updateThemeColor())
    12. }
    13. _updateThemeColor () {
    14. const { store } = this.context
    15. const state = store.getState()
    16. this.setState({ themeColor: state.themeColor })
    17. }
    18. // dispatch action 去改变颜色
    19. handleSwitchColor (color) {
    20. const { store } = this.context
    21. store.dispatch({
    22. type: 'CHANGE_COLOR',
    23. themeColor: color
    24. })
    25. }
    26. render () {
    27. return (
    28. <div>
    29. <button
    30. style={{ color: this.state.themeColor }}
    31. onClick={this.handleSwitchColor.bind(this, 'red')}>Red</button>
    32. <button
    33. style={{ color: this.state.themeColor }}
    34. onClick={this.handleSwitchColor.bind(this, 'blue')}>Blue</button>
    35. </div>
    36. )
    37. }
    38. }

    接下来,我们再看看如果用hooks如何实现,hooks主要的区别在于接受context的时候需要用到useContext这个API

    1. import { ThemeContext } from './Provider'
    2. class Index = (props) => {
    3. const context = useContext(ThemeContext)
    4. const [ themeColor, setState ] = useState({ themeColor: '' })
    5. useEffetcs(()=> {
    6. const { store } = context
    7. this._updateThemeColor()
    8. store.subscribe(() => _updateThemeColor())
    9. }, [])
    10. const _updateThemeColor = () => {
    11. const { store } = context
    12. const state = store.getState()
    13. setState({ themeColor: state.themeColor })
    14. }
    15. // dispatch action 去改变颜色
    16. const handleSwitchColor = (color) {
    17. const { store } = context
    18. store.dispatch({
    19. type: 'CHANGE_COLOR',
    20. themeColor: color
    21. })
    22. }
    23. render () {
    24. return (
    25. <div>
    26. <button
    27. style={{ color: this.state.themeColor }}
    28. onClick={handleSwitchColor('red')}>Red</button>
    29. <button
    30. style={{ color: this.state.themeColor }}
    31. onClick={this.handleSwitchColor('blue')}>Blue</button>
    32. </div>
    33. )
    34. }
    35. }