前端小誌(轉型中)

一個用來記錄人老會忘記的地方

HOC in React

2017年09月17日

React強調composition > inheritance,利用許多小的component組合成大的comoponent

其中,High-order component也是代替inheritance的一種方式。HOC為一個function,接收一個component為params,然後回傳另一個component。最常見的HOC就是react-redux的connect,此function幫助整個app可以綁定唯一的store,將邏輯與UI分離卻又很方便的建立component。

hocFactory:: W: React.Component => E: React.Component

對我來說,最大的好處就是不同的component可以使用HOC掛載相同的行為或屬性。

const Logger = (WrappedComponent) => {

 return class ClickLogger extends React.Component {
    handleClick => (e) {
      console.log(e)
    }

    render() {
      return (
        <WrappedComponent {...this.props} onClick={this.handleClick} />
      );
    }
  }

}

上述的function可以綁定任何的component,也是為什麼composition比inheritance好的原因。不過這其實這應該回到oo design討論,若只是為了code reuse,完全不應該使用inheritance。inheritance分為implementation inheritance(實作繼承)與interface inheritance(介面繼承),我們應該為了interface而繼承(is-a的概念),而implementation inheritance則使用composition取代。

並且,inheritance擁有最高的耦合度,在現在流行的functional progaming完全相反,或者說,functional progaming的一部份目的本來就是為了降低耦合度。

另外一個使用情境就是對props做一些處理,例如修改或是新增props (props proxy)

const Loggin = (WrappedComponent) {

  return class LogginWrap extends React.Component {

    render() {
      const newProps = {
        user: currentLoggedInUser
      }

      return <WrappedComponent
        {
          ...this.props,
          organization: this.props.organization.toUpperCase(),
        }
        { ...newProps }
      />
    }

  }
}

這篇文章還有更多應用像是inheritance inversion(看了一下很有趣,debug part看起來很好用,另一個不知道使用境),然後naming超實用!!

HOC.displayName = `HOC(${getDisplayName(WrappedComponent)})`
//or
class HOC extends ... {
  static displayName = `HOC(${getDisplayName(WrappedComponent)})`
  ...
}

Decorator與Recompose研究一下,下一篇再介紹。


展開Disqus
分類
最近文章
友站連結
© 2019 Ernie Yang