React react-redux 及其源码

115 阅读1分钟

Provider:把store注册到上下文中

import store from './store'

import { Provider } from 'react-redux'

root.render(
  <Provider store={store}>
    <Vote />
  </Provider>
)

connect:把公共状态和派发任务当做属性传递给属性

  • 自动获取上下文中的store

  • 自动把让组件更新的方法注册到store事件池中

  • mapStateToProps

  • mapDispatchToProps

import { connect } from 'react-redux'

const Vote = function Vote(props) {
  let { supNum, oppNum } = props

  return <div className="vote-box">...</div>
}

export default connect((state) => {
  return state.vote
})(Vote)
import actions from '@/store/actions'

import { connect } from 'react-redux'

const VoteFooter = function VoteFooter(props) {
  let { support, oppose } = props

  return (
    <div className="footer">
      <button onClick={support}>支持</button>

      <button onClick={oppose}>反对</button>
    </div>
  )
}

export default connect(
  null,

  (dispatch) => {
    return {
      support() {
        dispatch(actions.vote.support(10))
      },

      oppose() {
        dispatch(actions.vote.oppose())
      }
    }
  }
)(VoteFooter)
// 或者
<button onClick={support.bind(null, 10)}>支持</button>

export default connect(
  null,

  actions.vote
)(VoteFooter)

react-redux源码

import {
  createContext,
  useContext,
  useLayoutEffect,
  useMemo,
  useState
} from 'react'

import { bindActionCreators } from 'redux'

// 创建上下文对象

const ThemeContext = createContext()

// Provider

export function Provider(props) {
  return (
    <ThemeContext.Provider
      value={{
        store: props.store
      }}
    >
      {props.children}
    </ThemeContext.Provider>
  )
}

// connect

export function connect(mapStateToProps, mapDispatchToProps) {
  if (!mapStateToProps) {
    mapStateToProps = function mapStateToProps() {
      return {}
    }
  }

  if (!mapDispatchToProps) {
    mapDispatchToProps = function mapDispatchToProps() {
      return {}
    }
  }

  return function HOC(Component) {
    return function Proxy(props) {
      let { store } = useContext(ThemeContext),
        { getState, dispatch, subscribe } = store

      // 处理状态

      let state = getState()

      state = useMemo(() => mapStateToProps(state), [state])

      // 处理任务派发

      let dispatchToProps = useMemo(() => {
        if (typeof mapDispatchToProps === 'function') {
          return mapDispatchToProps(dispatch)
        }

        return bindActionCreators(mapDispatchToProps, dispatch)
      }, [dispatch])

      // 向事件池注入方法

      const [, forceUpdate] = useState(0)

      useLayoutEffect(() => {
        return subscribe(() => forceUpdate(+new Date()))
      }, [subscribe])

      return <Component {...props} {...state} {...dispatchToProps} />
    }
  }
}