老外写的一个react高阶组件

Posted by Turingdo Studio on May 29, 2018

老外写的一个React High-Order Component

版本一 LoaderHOC

import react,{Component} from 'react';
import './LoaderHOC.css';

const LoaderHOC => WrappedComponent=> {
  return class LoaderHOC extends Component{
    render(){
      return this.props.contacts.length === 0 ? <div className="loader"></div> : <WrappedComponent {...this.props} /> 
    }
  }
 
}

应用

//ContactsApp.js
@LoaderHOC
export default class ConcactsApp extends Component{}

// export default LoaderHOC(ConcactsApp);

版本二(升级) LoaderHOC

升级后,代码更加严谨,更加通用,可扩展

import react,{Component} from 'react';
import './LoaderHOC.css';

const LoaderHOC => propName => WrappedComponent=> {
  return class LoaderHOC extends Component{
    isEmpty(prop){
      return (
        prop === null ||
        prop === undefined ||
        (props.hasOwnProperty('length') && prop.length === 0) ||
        (prop.constructor === Object && Object.keys('length') === 0)
      )
    }
    render(){
      return this.isEmpty(this.props[propName]) ? <div className="loader"></div> : <WrappedComponent {...this.props} /> 
    }
  }
 
}

应用

//ContactsApp.js
@LoaderHOC('contacts')
export default class ConcactsApp extends Component{}

// export default LoaderHOC('contacts')(ConcactsApp);

react高阶组件

@修饰符 默认仅仅把class类当做第一个参数 ,如需添加其他参数,需要在闭包中返回一个可以接收该组件的函数

  • 例如
    function injectIntlComponent(options = { withRef: false }) {
    return (Component) => injectIntl(Component, options);
    }
    
import React from 'react';
import { DatePicker, Pagination, LocaleProvider } from 'antd';
import { FormattedMessage, injectIntl, addLocaleData, IntlProvider,
  defineMessages } from 'react-intl';
import InjectExample from './InjectExample';

const appLocale = window.appLocale;
addLocaleData(appLocale.data);


const messages = defineMessages({
  datePicker: {
    id: 'App.datePicker.title',
    defaultMessage: '日期选择-->test Inner',
  },
  datePicker2: {
    id: 'App.datePicker2.title',
    defaultMessage: '日期选择-->Inner',
  },
  title: {
    id: 'App.title',
    defaultMessage: '测试一下',
  },
});


const packIntlComponent = (localConfig = {}) => (Component) => {
  return class P extends React.Component {
    render() {
      return (
        <LocaleProvider locale={localConfig.antd}>
          <IntlProvider locale={localConfig.locale} messages={localConfig.messages}>
            <Component />
          </IntlProvider>
        </LocaleProvider>
      );
    }
  };
};

function injectIntlComponent(options = { withRef: false }) {
  return (Component) => injectIntl(Component, options);
}


@packIntlComponent(appLocale)
@injectIntlComponent()
class App extends React.Component {
  render() {
    return (<div style=>
      <div style=>
        <p><a href="index.html">中文</a></p>
        <p><a href="index-en.html">english</a></p>
      </div>
      <div style=>
        <FormattedMessage {...messages.datePicker} />: &nbsp;
        <DatePicker />
      </div>
      <div style=>
        <FormattedMessage {...messages.datePicker2} />: &nbsp;
        <DatePicker />
      </div>
      <div style=>
        <Pagination showQuickJumper defaultCurrent={2} total={500} />
      </div>
      <div style=>
        <InjectExample title={this.props.intl.formatMessage(messages.title)} />
      </div>
    </div>);
  }
}

export default App;