簡體   English   中英

反應-應該將高階組件編寫為函數嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM