React HOC(高階元件)

DC_er發表於2019-05-22

首先打個廣告,系列文章:

  1. 古老的React mixins
  2. HOC(高階元件)
  3. render props
  4. React Hooks

下面進入正題:

什麼是HOC

我們寫的純函式元件只負責處理展示,很多時候會發現,由於業務需求,元件需要被“增強”,例如響應瀏覽器事件等。如果只有一兩個元件我們大可以全部重寫為class形式,但如果有許多元件需要進行相似或相同的處理(例如都響應瀏覽器視窗改變這個事件)時,考慮到程式碼的複用性,很容易想到用函式處理,HOC也正是為了解決這樣的問題而出現的。

說白了,高階元件的存在和React mixins類似,都是為了解決程式碼複用的問題。

基本原理

HOC高階元件的基本原理可以寫成這樣:

const HOCFactory = (Component) => {
  return class HOC extends React.Component {
    render(){
      return <Component {...this.props} />
    }
  }
}
複製程式碼

很明顯HOC最大的特點就是:接受一個元件作為引數,返回一個新的元件

舉個?

我們還沿用上篇文章中響應滑鼠事件的的?。

import React from 'react'
import ReactDOM from 'react-dom'

const withMouse = (Component) => {
  return class extends React.Component {
    state = { x: 0, y: 0 }

    handleMouseMove = (event) => {
      this.setState({
        x: event.clientX,
        y: event.clientY
      })
    }

    render() {
      return (
        <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
          <Component {...this.props} mouse={this.state}/>
        </div>
      )
    }
  }
}

// APP是一個純函式無狀態元件
const App = (props) => {
  const { x, y } = props.mouse
  return (
    <div style={{ height: '100%' }}>
      <h1>The mouse position is ({x}, {y})</h1>
    </div>
  ) 
}

const AppWithMouse = withMouse(App)

ReactDOM.render(<AppWithMouse/>, document.getElementById('root'))
複製程式碼

優劣分析

優點:

  • 支援ES6,光這一項就戰勝了mixins
  • 複用性強,HOC是純函式且返回值仍為元件,在使用時可以多層巢狀,在不同情境下使用特定的HOC組合也方便除錯。
  • 同樣由於HOC是純函式,支援傳入多個引數,增強了其適用範圍。

當然HOC也存在一些問題(不然我就不會寫這篇文章了...)

  • 當有多個HOC一同使用時,無法直接判斷子元件的props是哪個HOC負責傳遞的。
  • 重複命名的問題:若父子元件有同樣名稱的props,或使用的多個HOC中存在相同名稱的props,則存在覆蓋問題,而且react並不會報錯。當然可以通過規範名稱空間的方式避免。
  • 可以發現HOC產生了許多無用的元件,加深了元件層級。

所以即使React HOC(高階元件)比古老的React mixins在解決程式碼複用問題上進步了不少,但是依然不能令人滿意。進一步的方案,參考下篇文章:React render props。

相關文章