React 高階應用 -- 高階元件 Heigher Order Component

garynan發表於2019-03-31

GitHub 學習 Demo。

高階元件 是 React 中重用元件的主要實現方式。但高階元件本身並不是 React API,它只是一種模式。

具體而言,高階元件就是一個函式,且該函式接受一個元件作為引數,並返回一個新的元件。

function Section() {
  return <section>Section</section>
}

function higherOrderComponent(BasicalComponent) {
  return (
    <artical>
      <header>Header</header>
      <hr>
      <BasicalComponent />
      <hr>
      <footer>Footer</footer>
    </artical>
  );
}

const Paga1 = higherOrderComponent(Section);
複製程式碼

注意,高階元件既不會修改輸入元件,也不會使用繼承拷貝它的行為。 而是,高階元件 組合(composes) 原始元件,通過用一個容器元件 包裹著(wrapping) 原始元件。高階元件就是一個沒有副作用的純函式。

簡單地說,就是在不汙染輸入元件的情況下,輸出一個功能更豐富的新元件。

function Button(props) {
  return <button onClick={props.onClick}>{props.children}</button>
}

function setClickCounter(Component, config = {}) {
  return class extends React.Component {
    constructor(porps) {
      super(porps);
      
      const {name, id, completeTime} = config;

      this.clicked = this.clicked.bind(this);

      this.state = {
        name,
        id,
        completeTime,
        count: 0,
        isFinished: false
      }
    }

    clicked() {
      if (this.state.isFinished) return;
      const {name, id, completeTime} = this.state;
      this.setState(preState => {
        const count = preState.count +1;
        const isFinished = count >= completeTime;
        console.log(`"${name}" 點選了 ${count}/${completeTime} 次 [${isFinished? '已完成':'未完成'}]`);
        return {count, isFinished};
      });
    }
    
    render() {
      const {name, isFinished} = this.state;
      const {children, otherProps} = this.props;
      if (isFinished) return `${name} [已完成]。`;
      return (
        <Component onClick={this.clicked} {...otherProps}>
          {children}
        </Component>
      );
    }
  }
}

const SuperBtnA = setClickCounter(Button, {
  name: 'A點選事件',
  id: 'A',
  completeTime: 10,
});
const SuperBtnB = setClickCounter(Button, {
  name: 'B點選事件',
  id: 'B',
  completeTime: 15,
});
複製程式碼

相關文章