React 团队从一开始就很注重 React 的代码复用性
他们对代码复用性的解决方案历经:Mixin, HOC, Render Prop,直到现在的 Custom Hook
所以 Custom Hook 并不是一拍脑门横空出世的产物,即使是很多对 Custom Hook 有丰富开发经验的开发者,也不了解 Hook 到底是怎么来的,以及在 React 里扮演什么角色
不理解这段设计思路是无法深刻的理解 Custom Hook 的,今天我们就一起来学习一下
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.forEach(clearInterval);
}
};
var createReactClass = require('create-react-class');
var TickTock = createReactClass({
mixins: [SetIntervalMixin], // 使用 mixin
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000); // 调用 mixin 上的方法
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});
ReactDOM.render(
<TickTock />,
document.getElementById('example')
);
优点:
缺点:
React.createClass
里工作,不支持 ES6 的 Class Component在 React 官网中已经被标记为 '不推荐使用',官方吐槽点这里
2015 年开始,React 团队宣布不推荐使用 Mixin,推荐大家使用 HOC 模式
HOC 采用了 '装饰器模式' 来复用代码
function withWindowWidth(BaseComponent) {
class DerivedClass extends React.Component {
state = {
windowWidth: window.innerWidth,
}
onResize = () => {
this.setState({
windowWidth: window.innerWidth,
})
}
componentDidMount() {
window.addEventListener('resize', this.onResize)
}
componentWillUnmount() {
window.removeEventListener('resize', this.onResize);
}
render() {
return <BaseComponent {...this.props} {...this.state}/>
}
}
return DerivedClass;
}
const MyComponent = (props) => {
return <div>Window width is: {props.windowWidth}</div>
};
经典的 容器组件与展示组件分离 (separation of container presidential) 就是从这里开始的