反应高阶组件

时间:2017-05-18 14:18:43

标签: reactjs font-awesome higher-order-components

我创建了这个HOC,用户可以传递两个组件,并返回一个字体真棒堆栈图标。

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>
   );
};

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

例如,

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. 有更好的方法吗?
  3. 我确实尝试过这样的事情:

    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;
    

1 个答案:

答案 0 :(得分:1)

您无法在propTypes上设置StackIcons,因为它不是一个组件。它返回组件。因此,您需要在返回的组件上设置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={{...}} />