# react-redux的实现原理
在普通的redux使用过程中,一般在组件内需要以下两个步骤:
- 在
componentDidMount
中进行订阅store中状态的更新 - 在组件使用
dispatch(action)
进行异步行为分发
import React, { Component } from 'react'
import { store } from '../redux/store';
import * as action from '../redux/action';
export default class Home extends Component {
state = {
num: store.getState()
}
componentDidMount() {
store.subscribe(() => {
this.setState({ num: store.getState() })
})
}
render() {
return (
<div>
Home---{this.state.num}
<button onClick={() => { store.dispatch(action.add(1)) }}>点我+1</button>
<button onClick={() => { store.dispatch(action.del(1)) }}>点我-1</button>
</div>
)
}
}
上面的组件中都会有subscribe
和dispatch
的部分。所以我们现在需要把这两个部分提取出来,然后所有组件就都可以进行复用了。
# connect高阶函数:
so我们定义一个connect函数connect(mapStateToProps, mapDispatchToProps)
:
- 参数一:里面存放
component
希望使用到的State
属性; - 参数二:里面存放
component
希望使用到的dispatch
动作; - 返回值:是一个高阶组件其参数是传入需要连接的组件,返回值是连接后的组件。
import React, { PureComponent } from "react";
import store from '../store';
export default function connect(mapStateToProps,mapDispatchToProps) {
return function handleMapCpn(WrappedComponent) {
return class extends PureComponent {
constructor(props) {
super(props);
this.state = {
storeState: mapStateToProps(store.getState())
}
}
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.setState({
storeState: mapStateToProps(store.getState())
})
})
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
return <WrappedComponent
{...this.props}
{...mapStateToProps(store.getState())}
{...mapDispatchToProps(store.dispatch)}/>
}
}
}
此时我们项目中的任意组件,想要和redux容器进connect连接,就只需要如下操作:
const mapStateToProps = state => {
return {
num: state.num
}
}
const mapDispatchToProps = dispatch => {
return {
addNumber: function(number) {
dispatch(action.add(number));
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
# context组件传值:
此时我们的Home组件怎么才能使用到store容器中的state状态呢?
我们就开始引入共享context来各组件间传值:
1.在入口文件index.js中使用Provider包裹根组件,传入需要共享的状态容器。
import store from './store';
import { createContext } from 'react';
ReactDOM.render(
<StoreContext.Provider value={store}>
<App />
</StoreContext.Provider>,
document.getElementById('root')
);
export const StoreContext = createContext();
2.进一步修改connect函数中使用consumer进行包裹使用共享容器store中的状态。
import React, { PureComponent } from "react";
import { StoreContext } from './index';
export default function connect(mapStateToProps, mapDispatchToProps) {
return function handleMapCpn(WrappedComponent) {
class ConnectCpn extends PureComponent {
constructor(props, context) {
super(props);
this.state = {
storeState: mapStateToProps(context.getState())
}
}
componentDidMount() {
this.unsubscribe = this.context.subscribe(() => {
this.setState({
storeState: mapStateToProps(this.context.getState())
})
})
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
return <WrappedComponent
{...this.props}
{...mapStateToProps(this.context.getState())}
{...mapDispatchToProps(this.context.dispatch)} />
}
}
ConnectCpn.contextType = StoreContext;
//类组件的消费共享context方式,相当于使用consumer包裹
return ConnectCpn;
}
}
就可以我们就可以在ConnectCpn组件中对redux中的全局状态容器进行操作,返回对应的Home组件。