中
接上一篇优化home.js与about.js中的代码:
思路.jpg
优化思路.jpg
优化后about.js
import React from "react";
import { connect } from "../utils/connect";
import { decAction, subAction } from "../store/actionCreators";
function About(props) {
return (
<div>
<hr />
<h1>About</h1>
<h2>当前计数: {props.counter}</h2>
<button onClick={(e) => props.decrement()}>-1</button>
<button onClick={(e) => props.subNumber(5)}>-5</button>
</div>
);
}
const mapStateToProps = (state) => {
return {
counter: state.counter,
};
};
const mapDispatchToProps = (dispatch) => {
return {
decrement: function () {
dispatch(decAction());
},
subNumber: function (num) {
dispatch(subAction(num));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(About);
优化后home.js与about.js一样,只是调用的action不一样;
//类组件home
import React, { PureComponent } from 'react';
import {connect} from '../utils/connect';
import { incAction, addAction } from '../store/actionCreators'
class Home extends PureComponent {
render() {
return (
<div>
<h1>Home</h1>
<h2>当前计数: {this.props.counter}</h2>
<button onClick={e => this.props.increment()}>+1</button>
<button onClick={e => this.props.addNumber(5)}>+5</button>
</div>
)
}
}
const mapStateToProps = state => ({
counter: state.counter
})
const mapDispatchToProps = dispatch => ({
increment() {
dispatch(incAction());
},
addNumber(num) {
dispatch(addAction(num));
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Home);
utils/connect.js
import React, { PureComponent } from "react";
import store from '../store';
export function connect(mapStateToProps, mapDispachToProp) {
return function enhanceHOC(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())}
{...mapDispachToProp(store.dispatch)} />
}
}
}
}
至此,封装完成了
思考:不止当前项目需要connect函数,那么最好的办法是把它封装成库,然后上传到npm,但是,当前还不够独立,因为它依赖了外部引入的store,也就是对业务逻辑有了依赖。问题:依然需要拿到store,但是不能通过导入的方式了。
解决方案:
手动封装库文件
utils/context.js
import React from 'react';
const StoreContext = React.createContext();
export {
StoreContext
}
utils/connect.js
import React, { PureComponent } from "react";
import { StoreContext } from './context';
export function connect(mapStateToProps, mapDispachToProp) {
return function enhanceHOC(WrappedComponent) {
class EnhanceComponent extends PureComponent {
constructor(props, context) {
super(props, context);
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())}
{...mapDispachToProp(this.context.dispatch)} />
}
}
EnhanceComponent.contextType = StoreContext;
return EnhanceComponent;
}
}
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import store from './store';
import { StoreContext } from './utils/context';
import App from './App';
ReactDOM.render(
<StoreContext.Provider value={store}>
<App />
</StoreContext.Provider>,
document.getElementById('root')
);
至此,到时候封装库的话只需要导出context与connect就行。
直接用第三方库文件
yarn add react-redux
src/index.js
对比自己封装的,使用时候会有一点点不一样
import React from 'react';
import ReactDOM from 'react-dom';
import store from './store';
// import { StoreContext } from './utils/context';
import { Provider } from 'react-redux';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
pages/about.js与pages/home.js,均使用第三方的connect就行
import React from "react";
// import { connect } from "../utils/connect";
import { connect } from 'react-redux';
import { decAction, subAction } from "../store/actionCreators";
function About(props) {
return (
<div>
<hr />
<h1>About</h1>
<h2>当前计数: {props.counter}</h2>
<button onClick={(e) => props.decrement()}>-1</button>
<button onClick={(e) => props.subNumber(5)}>-5</button>
</div>
);
}
const mapStateToProps = (state) => {
return {
counter: state.counter,
};
};
const mapDispatchToProps = (dispatch) => {
return {
decrement: function () {
dispatch(decAction());
},
subNumber: function (num) {
dispatch(subAction(num));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(About);
网友评论