React 高階組件使用心得

高階組件(HOC)是 React 中用於複用組件邏輯的一種高級技巧。HOC 自身不是 React API 的一部分,它是一種基於 React 的組合特性而造成的設計模式。
具體而言,高階組件是參數爲組件,返回值爲新組件的函數。
還不瞭解高階組件的點這裏

最近在作項目的時候遇到了一個情形:在系統後臺存在多個全局設置開關,例如在多個頁面都須要請求會員設置的開關。若是在每一個須要調用全局設置的地方都去請求一下接口,就會有一種不優雅的感受,這個時候我就想到利用高階組件抽象一下。html

版本一

getMemberSettingHoc = Component => class ContainerComponent extends React.Component {
    state = {
       loading: true,
       memberSetting: ''
    }
    componentDidMount() {
        Api.getSetting().then(memberSetting => {
            this.setState({ memberSetting })
        })
        ...doSomething
    }
    
    render() {
        return (
            <Component {...this.props} memberSetting={this.state.memberSetting} />
        )
    }
}

// 使用高階組件
class Home extends Component {
   ...
}
export default getMemberSettingHoc(Home);

這個時候看起來編寫一個 getMemberSettingHoc 的高階組件能夠讓咱們複用獲取會員設置的邏輯react

版本二

這個時候若是又多了幾個全局開關,例如:交易設置,支付設置,預定設置...編程

問題來了,這個時候咱們還須要編寫更多的高階組件來抽象這些設置嗎?

答案是否認的,咱們能夠實現一個 preMountHoc 來處理這些請求,顧名思義, preMountHoc 就是在掛載以前作事情的高階組件。設計模式

代碼以下函數式編程

const preMountDecorator = doSomething => ContentComponent => class PreMountComponent extends React.Component {

}

咱們傳入了一個參數,這個參數來傳入要請求的接口 doList 和返回的字段 keyList ,在 PreMountComponent 掛載的時候去 doSomething, 而後經過props,傳回給傳入的 ContentComponent.函數

咱們看下代碼this

// preMountHoc
const preMountHoc = doSomething => ContentComponent => class PreMountComponent extends React.Component {
    constructor() {
        super();

        this.state = {
            loading: true,
            result: {},
        };
    }

    componentDidMount() {
        const doList = get(doSomething, 'doList', []);
        const doListLength = get(doList, 'length') || 0;
        const keyList = get(doSomething, 'keyList', []);
        const keyListLength = get(keyList, 'length') || 0;
        if (doListLength == 0) {
            this.setState({ loading: false });
            return;
        }

        Promise.all(doList).then((res) => {
            const result = {};
            if (doListLength == keyListLength) {
                keyList.forEach((el, index) => {
                    result[el] = res[index];
                });
            } else {
                doList.forEach((el, index) => {
                    result[`pre_${index}`] = res[index];
                });
            }

            this.setState({ result, loading: false });
        });
    }

    render() {
        const { loading, result } = this.state;
        if (loading) {
            return <BlockLoading loading />;
        }

        return (
            <ContentComponent {...result} {...this.props} />
        );
    }
};

export default preMountHoc;

給 preMountHoc 傳入的須要的請求和返回的字段名,就能夠達到咱們的目的,來看看使用方法設計

class ScrmList extends Component {
    ...
}

export default preMountHoc({
    doList: [settingApi.getPower(), settingApi.hasMemberThreshold()],
    keyList: ['memberStoreSetting', 'scrmConditionType'],
})(ScrmList)

固然高階組件也是裝飾器,你也能夠這麼用code

@preMountHoc({
    doList: [settingApi.getPower(), settingApi.hasMemberThreshold()],
    keyList: ['memberStoreSetting', 'scrmConditionType'],
})
class ScrmList extends Component {
    ...
}

export default ScrmList;

總結

高階組件並非 React 的特性,是函數式編程的一種範式,最大的好處就是解耦和靈活性,在這分享下最近項目中的思考。component

相關文章
相關標籤/搜索