学习目标:
- 实现connect高阶组件
- 实现Provider
资源:
- react-redux API www.redux.org.cn/docs/react-…
- react-redux 源码 github.com/reduxjs/rea…
首先通过react-redux API去实现一个组件
- 项目入口文件
import React from 'react';
import ReactDOM from 'react-dom/client';
// import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import store from './store'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
- 创建一个使用connect的组件
import React from 'react'
import { connect } from 'react-redux'
class ReactReduxPage extends React.Component {
add = () => {
this.props.dispatch({ type: 'ADD' })
}
render() {
return (
<div>
{ console.log(this.props,'props')}
<button onClick={this.add}>dispatch: add</button>
<p>{this.props.count}</p>
</div>
)
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
dispatch
}
}
const mapStateToProps = (state, ownProps) => {
return state
}
export default connect(mapStateToProps,mapDispatchToProps)(ReactReduxPage)
首先我们去实现一个Provider组件
- 思考: 通过上述入口文件的代码可以了解到,provider接收store和后代组件
- 那么,当我们想让后代子孙组件可以使用当前的store,就会行程跨组件通信,而实现跨组件通信的方法context全局对象方法
- 所以引出我们需要创建一个context对象,然后通过context.Provider的value参数把store传递给后代子孙组件
再去实现一个connect的高阶函数
- 思考: 高阶组件connect接收mapStateToProps,mapDispatchToProps,还有当前的组件和组件自带的一些参数
- 高阶函数会返回一个新的组件
- mapStateToProps是通过调用这个函数把更新后的state返回给这个函数
- 那么我更新后的state去哪里获取呢?? store的getState方法
- 那store就可以通过全局对象Context去获取
- mapDispatchToProps是通过这个函数把dispatch返回给这个函数
- 那么我的dispatch去哪里获取呢?? store的dispatch方法
- 那store就可以通过全局对象Context去获取
import react from 'react'
// 获取全局对象
const Context = react.createContext()
export default function Provider({ store, children }){
return <Context.Provider value={store}>{children}</Context.Provider>
}
const connect = (mapStateToProps,mapDispatchToProps) => WrapperComponent => props => {
// 1. 先获取store
// 后代消费子孙组件的store可以通过三种方法
// 1. contextType 只能用在类组件中,并且只能订阅一个
// 2. useContext 自定义hook使用
// 3. consumer 都可以用
const store = useContext(Context)
const { getState, dispatch, subscribe } = store
// 组件中需要使用mapStateToProps,mapDispatchToProps,所以返回这两个函数的值
// 调用mapStateToProps方法, 返回更新后的所有state
let stateProps = mapStateToProps(getState())
// 添加默认值
let dispatchProps = { dispatch }
// 有的时候传递给我们的mapDispatchToProps是个函数,所以需要我们去判断下当前是否为函数
if(typeof mapDispatchToProps === 'function') {
// 如果是函数就直接调用函数方法并且把dispatch直接传递过去
dispatchProps = mapDispatchToProps(dispatch)
} else if(typeof mapDispatchToProps === 'object') {
// 如果是对象就需要使用redux中的bindActionCreators来帮助我们在内容实现dispatch({type: 'ADD'}) 调用
dispatchProps = bindActionCreators(mapDispatchToProps, dispatch)
}
return <WrapperComponent {...props} {...stateProps} {...dispatchProps}/>
}
这样我们就实现一个简单的react-redux中的Provider和connect