反应高阶组件

React Higher Order Components

我创建了这个用户可以传入两个组件的 HOC,它 returns 字体很棒的堆栈图标。

const StackIcons = (BaseIcon, TopIcon) => (props) => {
   const { container, base, top } = props;
   return (
    <span className={`fa-stack fa-lg fa-${container}`}>
        <BaseIcon stack="2x" className="info" {...base} />
        <TopIcon stack="1x" isInverse={true} {...top} />
    </span>
   );
};

我需要区分容器、基础图标和顶部图标之间的不同道具,所以我决定传递一个对象,该对象具有 属性 容器(字符串)、基础(对象)和顶部(对象)。

例如,

const object = {
  container: 'lg',
  base: {
    stack: '2x',
    className: 'info'
  },
  top: {
    stack: '1x',
    isInverse: true
  }
}

我使用这种方法的最大问题是 propTypes 和 defaultProps 不起作用。

// StackIcons.defaultProps = {
//     base: {
//         stack: '2x',
//         className: 'info'
//     },
//     top: {
//         stack: '1x',
//         isInverse: true
//     },
//     container: 'lg'
// };

StackIcons.propTypes = {
    base: PropTypes.object.isRequired,
    top: PropTypes.object.isRequired,
    container: PropTypes.oneOf(['lg', '2x', '3x', '4x', '5x']).isRequired,
};

由于 defaultProps 不起作用,我决定将它们注释掉并对基本和顶部图标组件的道具进行硬编码,但是消费者可以通过传递适当的道具来覆盖默认道具。

用法:

 const StackedIcons = StackIcons(<CircleIcon />, <DollarSign />);

 // in render method
 <StackedIcons /> // use default props

 // or override the defaultProps.
 <StackedIcons container="..." base={{...}} top={{...}} />
  1. 如何修复 propTypes 和 defaultTypes?
  2. 有没有更好的方法?

我确实尝试过这样的事情:

const StackIcons = (BaseIcon) => (baseIconProps) => (TopIcon) => (topIconProps) => {...}

但我不喜欢这样做:

const StackedIcons = StackIcons(<CircleIcon />)({ stack: '12x', className: 'info' })(<DollarSign />)

// in render method
<StackedIcons stack="1x" isInverse={true} /> 

非常感谢 Yury Tarabanko! 这是我更新后的工作版本:

import React from 'react';
import PropTypes from 'prop-types';

const stackIcons = (BaseIcon, TopIcon) => {

    const StackIcons = (props) => {
        const {container, base, top} = props;
        return (
            <span className={`fa-stack fa-lg fa-${container}`}>
                <BaseIcon {...base} />
                <TopIcon {...top} />
            </span>
        );
    };

    StackIcons.defaultProps = {
        base: {
            stack: '2x',
            className: 'info'
        },
        top: {
            stack: '1x',
            isInverse: true
        },
        container: 'lg'
    };

    StackIcons.propTypes = {
        base: PropTypes.object.isRequired,
        top: PropTypes.object.isRequired,
        container: PropTypes.oneOf(['lg', '2x', '3x', '4x', '5x']).isRequired,
    };

    return StackIcons;
};

export default stackIcons;

您不能在 StackIcons 上设置 propTypes,因为它不是组件。它 returns 组件。所以你需要在返回的组件上设置propTypes

const StackIcons = (BaseIcon, TopIcon) => {

   const Wrapped = props => ...

   Wrapped.propTypes = {}

   Wrapped.defaultProps = {}

   return Wrapped
};

用法应该是

 // here StackIcons is HOC
 // you can't use it like <StackIcons/>
 // but StackedIcons is just a stateless component
 const StackedIcons = StackIcons(CircleIcon, DollarSign);

 // so you can use it like this
 <StackedIcons /> // use default props

 // or override the defaultProps.
 <StackedIcons container="..." base={{...}} top={{...}} />