这是一个实际的例子。
import React from 'react';
require('./Headings.css');
let HeadingMixin = HeadingComponent => class extends React.Component {
constructor(props){
super(props)
}
render() {
return <HeadingComponent {...this.props} />
}
}
function Heading(props){
return (<h1 className={`${props.type}Heading`}>{props.text}</h1>)
}
Heading.propTypes = {
text: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.element,
]),
type: React.PropTypes.oneOf(['page', 'modal', 'sub', 'section']).isRequired,
}
export default Heading;
现在,每个组件呈现的实际HTML随元素和
className
的不同而不同。<h1 className="pageHeading">{props.text}</h1>
<h2 className="modalHeading">{props.text}</h2>
等等,使用
sub
和section
。现在,在
propTypes
,元素和classNames
之间,有没有更好的方法来选择呈现什么并使它们全部保持同步而不使用switch语句?作为替代方案,但类似的示例,这是我使用Icon类的方法。
import React from 'react';
require('./Icon.css');
const editGlyph = <path d="M5 14l-3-3 8-8 3 3zM11 2l2-2 3 3-2 2zM0 16l3-1-2-2" />;
const backGlyph = <path d="M2 7.994L8.137 16h4.312L6.31 7.994 12.45 0H8.136" />;
const addGlyph = <path d="M9.008 7.132V1H7.104v6.132H1v1.904h6.104v6.132h1.904V9.036h6.104V7.132" />;
const requiredGlyph = <path d="M4.79 3.42V1H3.655v2.42l-2.27-.857L1 3.59l2.27.815-1.392 1.95.964.662 1.392-2.055L5.71 7.017l.88-.663-1.414-1.95 2.334-.813-.428-1.027" />
const informationGlyph = <g transform="translate(0 .61)"><path d="M6.857 5.143h-2.57V6h.856v2.57h-.857v.86h3.428v-.86h-.857" /><ellipse cx="6" cy="3.429" rx=".857" ry=".857" /><path d="M6 0C2.687 0 0 2.687 0 6s2.687 6 6 6 6-2.687 6-6-2.687-6-6-6zm0 11.143C3.164 11.143.857 8.836.857 6S3.164.857 6 .857 11.143 3.164 11.143 6 8.836 11.143 6 11.143z" /></g>;
let iconGlyph;
export default function Icon(props) {
switch (props.glyph) {
case 'add':
iconGlyph = addGlyph;
break;
case 'back':
iconGlyph = backGlyph;
break;
case 'edit':
iconGlyph = editGlyph;
break;
case 'required':
iconGlyph = requiredGlyph;
break;
case 'i':
iconGlyph = informationGlyph;
break;
default:
iconGlyph = null;
break;
}
return (
<svg
id="icon"
className={[`icon ${props.className}`]}
viewBox="0 0 16 16"
aria-labelledby="title"
>
<title id={props.title}>{props.title}</title>
{iconGlyph}
</svg>
)
}
Icon.propTypes = {
glyph: React.PropTypes.oneOf(['add', 'back', 'edit', 'i', 'required']).isRequired,
className: React.PropTypes.string,
title: React.PropTypes.string,
}
我不知道这是什么,但是我无法撼动有一种更优雅的方式来处理此问题的感觉。也许有一些参数的装饰器?
最佳答案
如果我正确理解您的问题,则可以执行以下操作。 Demo。
const { oneOf, string } = PropTypes
// save all your options in hash
const icons = {
edit: <path d="M5 14l-3-3 8-8 3 3zM11 2l2-2 3 3-2 2zM0 16l3-1-2-2" />,
back: <path d="M2 7.994L8.137 16h4.312L6.31 7.994 12.45 0H8.136" />,
add: <path d="M9.008 7.132V1H7.104v6.132H1v1.904h6.104v6.132h1.904V9.036h6.104V7.132" />,
required: <path d="M4.79 3.42V1H3.655v2.42l-2.27-.857L1 3.59l2.27.815-1.392 1.95.964.662 1.392-2.055L5.71 7.017l.88-.663-1.414-1.95 2.334-.813-.428-1.027" />,
i: <g transform="translate(0 .61)"><path d="M6.857 5.143h-2.57V6h.856v2.57h-.857v.86h3.428v-.86h-.857" /><ellipse cx="6" cy="3.429" rx=".857" ry=".857" /><path d="M6 0C2.687 0 0 2.687 0 6s2.687 6 6 6 6-2.687 6-6-2.687-6-6-6zm0 11.143C3.164 11.143.857 8.836.857 6S3.164.857 6 .857 11.143 3.164 11.143 6 8.836 11.143 6 11.143z" /></g>
}
// Icon is stateless
const Icon = ({ type, className, title }) => (
<svg
id="icon"
className={[`icon ${className}`]}
viewBox="0 0 16 16"
aria-labelledby="title"
>
<title id={title}>{title}</title>
{/* Assuming type is the same as key in icons */}
{icons[type] || null}
</svg>
)
Icon.propTypes = {
// make this constain "dynamic"
glyph: oneOf(Object.keys(icons)).isRequired,
className: string,
title: string,
}