Hook 的发展历程

React 团队从一开始就很注重 React 的代码复用性

他们对代码复用性的解决方案历经:Mixin, HOC, Render Prop,直到现在的 Custom Hook

所以 Custom Hook 并不是一拍脑门横空出世的产物,即使是很多对 Custom Hook 有丰富开发经验的开发者,也不了解 Hook 到底是怎么来的,以及在 React 里扮演什么角色

不理解这段设计思路是无法深刻的理解 Custom Hook 的,今天我们就一起来学习一下

1. Mixin 💊

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')
);

优点:

  1. 确实起到了重用代码的作用

缺点:

  1. 它是隐式依赖,隐式依赖被认为在 React 中是不好的
  2. 名字冲突问题
  3. 只能在 React.createClass里工作,不支持 ES6 的 Class Component
  4. 实践下来发现:难以维护

在 React 官网中已经被标记为 '不推荐使用',官方吐槽点这里

2. HOC

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