jsxとReactの動的タグ名


162

Reactコンポーネントを記述しようとしています。html見出しタグ(h1、h2、h3など)の場合、見出しの優先度は、小道具で定義した優先度に基づいて動的に変化します。

ここで私がやろうとしていること。

<h{this.props.priority}>Hello</h{this.props.priority}>

予想される出力:

<h1>Hello</h1>

これは機能していません。これを行うための可能な方法はありますか?


回答:


328

それをその場で行う方法はありません。それを変数に入れます(最初の文字を大文字にします):

const CustomTag = `h${this.props.priority}`;

<CustomTag>Hello</CustomTag>

5
間違いなくより簡単ですReact.createClass、私はこの方法を好みます。ありがとう。
Vadorequest

@zerkms CustomTagに属性を追加する方法はありますか?感謝
サブリナ羅

1
@サブリナ<CustomTag foo="bar">
zerkms

ええと。これはどのように作動しますか?変数名が小文字の場合は、それをタグとして挿入するだけです(たとえば、それがcustomtagの場合、<customtag> Hello </ customtag>になります)。これはどこかに文書化されていますか?
イブラヒム

5
コンポーネントがオブジェクトのプロパティに格納されている場合は、最初の大文字は不要です。var foo = { bar: CustomTag }; return <foo.bar />正常に動作します。
2018年

29

完全React.createElementを期すために、動的な名前を使用したい場合は、JSXを使用する代わりに直接呼び出すこともできます。

React.createElement(`h${this.props.priority}`, null, 'Hello')

これにより、新しい変数またはコンポーネントを作成する必要がなくなります。

小道具を使って:

React.createElement(
  `h${this.props.priority}`,
  {
    foo: 'bar',
  },
  'Hello'
)

ドキュメントから:

指定されたタイプの新しいReact要素を作成して返します。type引数は、タグ名文字列('div'またはなど'span')、またはReactコンポーネントタイプ(クラスまたは関数)のいずれかです。

JSXで記述されたコードは、使用するように変換されますReact.createElement()React.createElement()JSXを使用している場合は、通常、直接呼び出すことはありません。詳細については、JSXを使用せずにReactを参照してください。


11

TypeScriptを使用している場合は、次のようなエラーが表示されます。

Type '{ children: string; }' has no properties in common with type 'IntrinsicAttributes'.ts(2559)

TypeScriptはそれCustomTagが有効なHTMLタグ名であることを認識せず、役に立たないエラーをスローします。

修正するには、CustomTagとしてキャストしてkeyof JSX.IntrinsicElementsください!

const CustomTag = `h${this.props.priority}` as keyof JSX.IntrinsicElements;

<CustomTag>Hello</CustomTag>

私は活字体上だが、それをキャストすると、このエラーを与える:Types of property 'crossOrigin' are incompatible. Type 'string | undefined' is not assignable to type '"" | "anonymous" | "use-credentials" | undefined'. Type 'string' is not assignable to type '"" | "anonymous" | "use-credentials" | undefined'.
缶Poyrazoğlu

8

他のすべての答えは問題なく機能していますが、これを行うことで次のようにいくつか追加します。

  1. 少し安全です。型チェックが失敗しても、適切なコンポーネントを返します。
  2. より宣言的です。このコンポーネントを見ると、誰でもそれが何を返すことができるかがわかります。
  3. たとえば、「h1」、「h2」などの代わりに、より柔軟性があります...見出しのタイプには、他の抽象的な概念「sm」、「lg」、「primary」、「secondary」を使用できます

見出しコンポーネント:

import React from 'react';

const elements = {
  h1: 'h1',
  h2: 'h2',
  h3: 'h3',
  h4: 'h4',
  h5: 'h5',
  h6: 'h6',
};

function Heading({ type, children, ...props }) {    
  return React.createElement(
    elements[type] || elements.h1, 
    props, 
    children
  );
}

Heading.defaultProps = {
  type: 'h1',
};

export default Heading;

あなたはそれを好きに使うことができます

<Heading type="h1">Some Heading</Heading>

または、別の抽象的な概念を持つことができます。たとえば、次のようなサイズの小道具を定義できます。

import React from 'react';

const elements = {
  xl: 'h1',
  lg: 'h2',
  rg: 'h3',
  sm: 'h4',
  xs: 'h5',
  xxs: 'h6',
};

function Heading({ size, children }) {
  return React.createElement(
    elements[size] || elements.rg, 
    props, 
    children
  );
}

Heading.defaultProps = {
  size: 'rg',
};

export default Heading;

あなたはそれを好きに使うことができます

<Heading size="sm">Some Heading</Heading>

2

動的見出し(h1、h2 ...)のインスタンスでは、コンポーネントはReact.createElement(上記のFelixで述べたように)そのように返すことができます。

const Heading = ({level, children, ...props}) => {
    return React.createElement(`h${level}`, props , children)
}

構成可能性のために、小道具と子の両方が渡されます。

例を見る

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.