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) 就是从这里开始的