想必我們都曾經遇過一種情境,兩個component功能幾乎一模一樣,只是差在輸入的資料不同而已,那麼這時候就是HOC登場的時候了,HOC為一個可以傳入component當參數的function,其目的在於可以將重複的邏輯抽離出來,讓傳入的component可以套用這個邏輯,並且輸出一個全新的component
當初看到redux的connect還想說這是什麼神秘的寫法,原來就是HOC啊!
const Counter = connect(
mapStateToProps,
mapDispatchToProps
)(Counters);
被作為參數的component稱之為Wrapped Component
以下就來實做一下HOC,這是HOC component,實現一個簡單的時鐘功能
可以看到HOC component接收到一個component之後,將計算後的結果(每秒更新當前時間)透過props傳遞到 wrapped component裡面
function WithTime(InnerComponent) {
class OuterComponent extends Component{
state = {
time: new Date().toLocaleTimeString()
}
componentDidMount(){
this.interval = setInterval(() => {
this.setState({
time: new Date().toLocaleTimeString()
})
}, 1000);
}
componentWillMount(){
clearInterval(this.interval)
}
render(){
return <InnerComponent time={this.state.time} />
}
}
return OuterComponent
}
這是要被傳入的component(僅負責ui,沒有邏輯處理),透過props取得hoc component輸入的資料,可以看到最後export 出去的是withTime回傳的新component
import React, { Component } from 'react'
import WithTime from './WithTime'
class HocExample extends Component{
render(){
return (<h1>{this.props.time}</h1>)
}
}
export default WithTime(HocExample)
恩…又報錯了
字面上好像是我傳入了不合法的格式?一開始以為是不能傳時間物件?搞了老半天才發現,其實問題是在render的地方直接渲染物件, 將state轉換一下格式換成時間字串就可以了。
toLocaleTimeString() 可以直接轉成當地時間字串
在估狗資料的時候一直看到HOC波動拳(HOC wrapper hell),想說那是啥,看到下面那張圖就瞬間明白了什麼,因為HOC包HOC,層層嵌套之下就會衍生這個問題,後面會再介紹React Hook如何解決這個問題。
圖片來源:推特作者@GrexQL