高階組件(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