2016-06-23 7 views
2

ここに実例があります。React:高次コンポーネントのレンダリングにはより良いパターンがありますか?

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によって異なります。 subsection

<h1 className="pageHeading">{props.text}</h1> 
<h2 className="modalHeading">{props.text}</h2> 

など。

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, 
} 

私はそれが何であるかわからないが、私はこれを処理するために、よりエレガントな方法があるという感覚を振り払うことができません。おそらくいくつかのパラメータを持つデコレータ?

答えて

3

私があなたの質問を正しく理解している場合は、次のことができます。 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, 
} 
+0

したがって、見出しの例はどうですか?これは、事前にどのHTML要素をレンダリングするかわからないため、難しいです。 –

+0

実際はありません。 https://codepen.io/tarabyte/pen/NrdWjO?editors=0010 'cloneElement'か、子をとり、ヘッダを返す関数を使うことができます。 –

+0

'createElement'を使うhttps://codepen.io/tarabyte/pen/OXWJzE –

関連する問題