Javascript 反应:是否有更好的模式用于高阶组件渲染?

Javascript 反应:是否有更好的模式用于高阶组件渲染?,javascript,reactjs,functional-programming,Javascript,Reactjs,Functional Programming,这里有一个实际的例子 import React from 'react'; require('./Headings.css'); let HeadingMixin = HeadingComponent => class extends React.Component { constructor(props){ super(props) } render() { return <HeadingComponent {...this.props} />

这里有一个实际的例子

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;
使用
sub
部分

现在,在
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,
}
从“React”导入React;
需要('./Icon.css');
常量editGlyph=;
const backGlyph=;
常量addGlyph=;
const requiredGlyph=
const informationGlyph=;
让我联系;
导出默认功能图标(道具){
开关(道具符号){
案例“添加”:
iconGlyph=addGlyph;
打破
“回来”一案:
iconGlyph=背面轮廓;
打破
案例“编辑”:
iconGlyph=编辑字形;
打破
案例“必需”:
iconGlyph=所需字形;
打破
案例“i”:
iconGlyph=信息字形;
打破
违约:
iconGlyph=null;
打破
}
返回(
{props.title}
{iconGlyph}
)
}
Icon.propTypes={
glyph:React.PropTypes.oneOf(['add','back','edit','i','required'])。需要,
类名:React.PropTypes.string,
标题:React.PropTypes.string,
}

我不知道这是什么,但我无法动摇有一种更优雅的方式来处理这件事的感觉。也许是一个有一些参数的装饰师?

如果我正确理解了你的问题,你可以做以下事情

const{oneOf,string}=PropTypes
//将所有选项保存在哈希中
常量图标={
编辑:,
背面:,
加:,
必需:,
一:
}
//图标是无状态的
常量图标=({type,className,title})=>(
{title}
{/*假设类型与键入图标相同*/}
{图标[类型]| | null}
)
Icon.propTypes={
//让这个康斯坦因“充满活力”
标志符号:需要(对象键(图标))之一,
类名:string,
标题:字符串,
}

那么,标题示例如何?这一点更为棘手,因为您不知道要提前呈现哪个HTML元素。您可以使用
cloneElement
或一个接受子元素并返回标题的函数。我的意思是,我想这与我在SVG/图标示例中使用的
元素的前提相同。我将尝试一下。谢谢关于装饰师还有什么评论吗?实际上我没有和装饰师玩太多。有点不喜欢另一种语法(
@BlahBlah()
)。但是一个接受params并返回一个接受component并返回另一个component的函数听起来不错:)
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,
}
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,
}