[英]React - should Higher Order Component be written as a function?
我正在學習React。 在我看來,HOC就像來自React官方文檔的以下示例:
function withSubscription(WrappedComponent, selectData) {
// ...and returns another component...
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ... that takes care of the subscription...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... and renders the wrapped component with the fresh data!
// Notice that we pass through any additional props
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
可以這樣重寫:
class WithSubscription extends React.Component {
constructor({ component, selectData, ...props }) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
return <component data={this.state.data} {...this.props} />;
}
}
然后像這樣使用它:
<WithSubscription component={BlogPost} selectData={(DataSource) => DataSource.getComments()} />
他們都是HOC嗎? 什么時候一種風格比另一種更好?
一開始,我也在HOC方面掙扎。 另一種查看方式是組件包裝,您可以使用這些組件將功能與一個組件隔離。
例如,我有多個HOC。 我有許多僅由props定義的組件,一旦創建,它們是不可變的。
然后,我有一個Loader HOC組件,該組件處理所有網絡連接,然后將道具傳遞給要包裝的任何組件(這就是您傳遞給HOC的組件)。
加載程序並不真正在乎它正在渲染哪個組件,它只需要獲取數據並將其傳遞給包裝的組件。
在您的示例中,您實際上可以完成此操作,但是一旦您需要鏈接多個HOC,它將變得更加復雜。
例如,我有此HOC鏈:
PermissionsHOC-> LoaderHOC-> BorderLayoutHOC-> Component
第一個可以檢查您的權限,第二個可以加載數據,第三個可以提供通用布局,第四個是實際組件。
如果您意識到某些組件將從父級上的通用邏輯中受益,則檢測HOC會容易得多。 您可以在示例中執行相同的操作,但是每次添加子組件時都需要修改HOC,以添加該子組件的邏輯。 不是很有效。 這樣,您可以輕松添加新組件。 我確實有一個Base組件,每個組件都可以擴展,但是我用它來處理諸如分析,記錄器,處理錯誤等輔助功能。
他們所謂的“ HOC”基本上是一個功能類似於組件工廠的函數(只是一個常規函數,不是特定於React的)。 這意味着它會輸出包裝的組件,這些組件是包裝您選擇的任何內部組件的結果 。 您的選擇由“ WrappedComponent”參數指定。 (請注意,他們所謂的“ HOC”實際上是如何返回一個類的)。
所以我不知道為什么他們稱其為“ HOC” TBH。 它只是一個吐出組件的函數。 如果有人知道為什么我會對聽到這個原因感興趣。
從本質上講,他們的示例確實在執行您的操作,但是它更靈活,因為WrappedComponent被作為參數使用。 因此,您可以指定任何內容。
另一方面,您的代碼將內部組件硬編碼到其中。
為了查看他們的示例的強大功能,假設您有一個名為insideComp.js的文件,其中包含:
import withSubscription from './withSubscription';
class InsideComp extends React.Component{
// define it
}
export default withSubscription(InsideComp);
當您在另一個文件中使用insideComp時:
import myComp from './insideComp.js';
您實際上不是在導入insideComp,而是在導入“ withSubscription”已經包裝好的版本。 因為請記住您的insideComp.js最后一行是
export default withSubscription(InsideComp);
因此,您的InsideComp在導出之前已被修改
第二個不是HOC。
他們從高階函數中創造了HOC一詞。 高階函數的一個示例是將函數作為參數並返回另一個函數的函數。
類似地,HOC是將一個組件作為參數並返回另一個組件的函數。
這對我來說確實很奇怪,因為高階分量不是反應分量。 它是一個函數。 我猜他們稱其為HOC的原因是:
React組件是一個類,它實際上是JavaScript中的構造函數(除了功能組件只是函數)。 HOC實際上需要一個函數(一個構造函數)並返回另一個函數(另一個構造函數),因此,考慮一下它實際上是一個高階函數。 可能是因為它在react上下文中,並且這是轉換組件的一種模式,因此他們將其稱為HOC。
關於您提到的兩種樣式之間的區別:
第一個:您將使用第一個生成類似MyComponnet = withSubscription(AnotherComponent, ...)
,只要在渲染調用中需要它,只需編寫<MyComponent><MyComponent>
第二個:這不太常見。 每次在渲染調用中需要它時,都需要包含描述中所述的<WithSubscription component={BlogPost} selectData={(DataSource) => DataSource.getComments()} />
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.