hello,大家好今天让我们一起实现下自己react-redux吧!上一篇我们分享了redux,不懂的可以直接查看额,本篇文章适合有一定基础的react开发人员,用到了react Context api 不懂的可以先查看下,文本较长,建议收藏,废话不说,直接上干货!!!
一、从入口文件开始
首先我们需要在入门文件index.js文件上做如下修改,引入我们自己的文件,这时候因为我们还没有建立文件,自然就报错了,莫慌往下进行
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from '@/pages/home'
// 引入我们自己的provider
import { Provider } from './myReactRedux/provider'
// 引入上期的store
import store from '@/store/store'
ReactDOM.render(
<React.StrictMode>
<Provider store={ store }>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
二、创建myReactRedux文件夹
我们在src目录下创建myReactRedux文件夹,在改文件夹下分别创建bindActionCreators.js connect.js createContext.js provider.js,我们先从最简单的provider.js开始创建
import React, { Component } from 'react'
// provider比较简单就是一个高阶组件
class Provider extends Component {
render() {
return (
<div>
{this.props.children}
</div>
)
}
}
export { Provider }
这里我们就可以页面内容了,那么我们的store数据怎么传递呢?
三、创建createContext.js内容
这里我们需要使用react给我们提供的api方法context,让数据可以向下传递
createContext.js代码比较简单我贴出了,就是原封的react api
import React from 'react'
// react context
const ValueContext = React.createContext();
export default ValueContext
此时我们回过头来给provider.js绑定store
import React, { Component } from 'react'
//引入
import ValueContext from './createContext'
class Provider extends Component {
render() {
return (
// context属性传递,这里去订阅了store的数据传递给了组件
<ValueContext.Provider value={ this.props.store}>
{this.props.children}
</ValueContext.Provider>
)
}
}
export { Provider }
此时我们就可以在控制台打印出我们this.props看下了,是不是很简答哇!
四、创建connect.js内容
先分析下结构,connect是一个函数,接收了两个参数并且传递给了组件,代码如下
import React, { Component } from 'react'
// 接收参数,组件,直接将组件返回
export const connect = (
mapStateToProps,
mapDispatchToProps
) => WrappedComponent => {
return class extends Component {
render() {
return <WrappedComponent />;
}
}
}
五、connect函数订阅数据传递给组件
我们的store数据使用了contect向下传递,我们首先引入创建的context获取上下文,和store数据
import React, { Component } from 'react'
import ValueContext from './createContext'
// 接收参数和组件,直接将组件返回
export const connect = (
mapStateToProps,
mapDispatchToProps
) => WrappedComponent => {
return class extends Component {
// 挂载contextType属性
static contextType = ValueContext
render() {
return <WrappedComponent />;
}
}
}
此时context就被我们挂载到了this上
六、mapStateToProps
state在我们传递过来的mapStateToProps上,他是一个函数,我们直接返回就好了,我们在mount阶段去处理数据,将值传递给组件就可以了
import React, { Component } from 'react'
import ValueContext from './createContext'
// 接收参数和组件,直接将组件返回
export const connect = (
mapStateToProps,
mapDispatchToProps
) => WrappedComponent => {
return class extends Component {
// 挂载contextType属性
static contextType = ValueContext
//为了修改props让组件更新变化,需要调用setState,所以这里重新创建下
constructor(props) {
super(props);
this.state = {
props: {}
};
}
componentDidMount() {
this.update();
//我们在mount阶段去获取一下context中的值
const { subscribe, getState } = this.context
subscribe(() => {
this.update();
})
}
update = () => {
const { getState, dispatch } = this.context;
//查看一下传递过来的类型
// console.log(mapStateToProps, mapDispatchToProps);
//直接返回state的值
const stateProps = mapStateToProps(getState())
let dispatchProps;
this.setState({
props: {
...stateProps,
...dispatchProps
}
});
}
render() {
return <WrappedComponent {...this.props} {...this.state.props}/>;
}
}
}
七、mapDispatchToProps
我们知道mapDispatchToProps可以接受一个对象或者函数,只不过函数需要使用bindActionCreators绑定下dispatch,所以这里要对他们分别进行处理,我们先给出bindActionCreators函数
function bindActionCreator(creator, dispatch) {
return (...args) => dispatch(creator(...args));
}
// 循环绑定包裹dispatch
function bindActionCreators(creators,dispatch) {
const obj = {};
for (const key in creators) {
obj[key] = bindActionCreator(creators[key],dispatch);
}
return obj;
}
export { bindActionCreators }
然后就可以实现我们的mapDispatchToPropsle
import React, { Component } from 'react'
import ValueContext from './createContext'
import { bindActionCreators } from './bindActionCreators'
// 接收参数和组件,直接将组件返回
export const connect = (
mapStateToProps,
mapDispatchToProps
) => WrappedComponent => {
return class extends Component {
// 挂载contextType属性
static contextType = ValueContext
constructor(props) {
super(props);
this.state = {
props: {}
};
}
componentDidMount() {
this.update();
//我们在mount阶段去获取一下context中的值
//看下context中有什么吧
// console.log(this.context)
const { subscribe, getState } = this.context
//这里已经可以看到我们的值了
// console.log(getState())
subscribe(() => {
this.update();
})
}
update = () => {
const { getState, dispatch } = this.context;
//查看一下传递过来的类型
// console.log(mapStateToProps, mapDispatchToProps);
//直接返回state的值
const stateProps = mapStateToProps(getState())
let dispatchProps;
if (typeof mapDispatchToProps === "object") {
// 办理object,分别绑定dispath方法
dispatchProps = bindActionCreators(mapDispatchToProps,dispatch);
} else if (typeof mapDispatchToProps === "function") {
// 绑定dispath方法
dispatchProps = mapDispatchToProps(dispatch, this.props);
} else {
// 直接绑定
dispatchProps = { dispatch };
}
this.setState({
props: {
...stateProps,
...dispatchProps
}
});
}
render() {
return <WrappedComponent {...this.props} {...this.state.props}/>;
}
}
}
ok,你学会了吗?快来试试新技能吧!