将道具传递给从对象动态渲染的组件

时间:2020-01-26 22:51:44

标签: javascript reactjs react-props higher-order-components

我有一个充满所有成分的对象:

const Icons = {
   // commonly used darksky icon names
   "clear-day": <ClearDayIcon />,
   "clear-night": <ClearNightIcon />,
   "rain": <RainMediumIcon />,
   "snow": <SnowIcon />,
   "sleet": <RainHeavyIcon />,
   "wind": <WindyDayIcon />,
   // etc..
}

每个组件实际上只是一个包装为react组件的svg。但是我需要它来接收来自其调用位置的道具,尤其是className道具。

我想做的就是以下列方式从其他组件中调用这些组件:

<WeatherIcon icon={icon} className="some-class" />

图标道具将在何处确定选择了哪个图标组件。所以我尝试了这个:

const WeatherIcon = props => Icons[ props.icon ]

所以这部分起作用,因为我可以编写<WeatherIcon icon={'clear-night'} />,并且呈现正确的组件。但是,无法将其他WeatherIcon组件中的其他道具向下传递到每个Icon中。例如,编写<WeatherIcon icon={'clear-night'} className="some-class" />显然不会将className道具(或任何其他道具)向下传递到每个单独的组件。我试图做这样的事情:

const Icons = {
   "clear-day": props => <ClearDayIcon {...props} />,
   "clear-night": props => <ClearNightIcon {...props} />,
   // etc..
}

但是这不起作用,因为现在我返回的是Component而不是<Component />。我在问题Passing props to dynamically loaded components中看到了解决方案,但是所有这些都建议像{ Icons['clear-day'](className: 'some-class', anotherProp: 'some-prop') }这样调用组件。我觉得这不是很优雅。必须有一种方法将其写为<WeatherIcon icon={'some-icon'} className={'some-class'} someProp={'some-prop'} />,并正确过滤道具。 (我确实意识到所有道具都会一直过滤到我的SVG组件-很好)。我觉得这里有一个更高阶的组件等待写,但是现在它使我难以理解。

感谢阅读

2 个答案:

答案 0 :(得分:1)

我不确定100%是否可以满足您的要求,但我可能会尝试这样的事情;

const Icons = {
   "clear-day": ClearDayIcon,
   "clear-night": ClearNightIcon,
   "rain": RainMediumIcon,
   "snow": SnowIcon,
   "sleet": RainHeavyIcon,
   "wind": WindyDayIcon,
   // etc..
}

const Icon = ({icon, ...rest}) => {
    const IconComponent = Icons[icon]

    if(!IconComponent) {
        // Or throw an exception maybe.
        // At least print some console warnings in development env.
        return null;
    }

    return <IconComponent {...rest} />
}

通过这种方式,您可以选择一个Icon组件并将任何道具传递给它。 而且当您要使用它时,您可以像这样使用它;

// ...
<Icon icon="clear-day" className="some-class" />
// ...

答案 1 :(得分:0)

我发现这也是可行的-将包含组件的对象编写为props函数,然后返回对象。然后,您可以在每个组件中使用{...props}

const Icons = props => ({
   "clear-day": <ClearDayIcon {...props} />,
   "clear-night": <ClearNightIcon {...props} />,
   "rain": <RainMediumIcon {...props} />,
   etc.
})

然后包装器组件如下所示:

const WeatherIcon = props => Icons(props)[ props.icon ]

非常简单-我知道我已经接近了。我不确定这是否被视为高阶组件(HOC)。它是一个 组件,它根据其道具返回另一个组件,并附加了新的道具。那算作HOC吗?