Nama tag dinamis dalam jsx dan Bereaksi

163

Saya mencoba menulis komponen Bereaksi. untuk tag heading html (h1, h2, h3, dll ...), di mana prioritas heading berubah secara dinamis berdasarkan prioritas yang telah kami tentukan dalam alat peraga.

Inilah yang saya coba lakukan.

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

output yang diharapkan:

<h1>Hello</h1>

Ini tidak bekerja. Apakah ada metode yang memungkinkan untuk melakukan ini?

Eranga Kapukotuwa
sumber
Kemungkinan duplikat nama komponen dinamis Bereaksi / JSX
Jordan Running

Jawaban:

329

Tidak ada cara untuk melakukan itu di tempat, cukup letakkan di dalam variabel ( dengan huruf kapital pertama ):

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

<CustomTag>Hello</CustomTag>
zerkms
sumber
5
Jelas lebih mudah daripada React.createClass, saya lebih suka cara ini. Terima kasih.
Vadorequest
@zerkms Anda tahu cara menambahkan atribut ke CustomTag? terima kasih
Sabrina Luo
1
@Sabrina<CustomTag foo="bar">
zerkms
Hah. Bagaimana cara kerjanya? Jika nama variabelnya huruf kecil, itu hanya menyisipkannya sebagai tag (mis. Jika itu customtag, saya akan mendapatkan <customtag> Hello </customtag>). Apakah ini didokumentasikan di mana saja?
Ibrahim
5
Jika komponen disimpan dalam properti objek, huruf kapital pertama tidak diperlukan. var foo = { bar: CustomTag }; return <foo.bar />bekerja dengan baik.
menyentak
29

Untuk kelengkapan, jika Anda ingin menggunakan nama dinamis, Anda juga dapat langsung menelepon React.createElementdaripada menggunakan JSX:

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

Ini menghindari keharusan membuat variabel atau komponen baru.

Dengan alat peraga:

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

Dari dokumen :

Buat dan kembalikan elemen Bereaksi baru dari tipe yang diberikan. Argumen tipe dapat berupa string nama tag (seperti 'div'atau 'span'), atau tipe komponen Bereaksi (kelas atau fungsi).

Kode yang ditulis dengan BEJ akan dikonversi untuk digunakan React.createElement(). Anda biasanya tidak akan meminta React.createElement()secara langsung jika Anda menggunakan JSX. Lihat Bereaksi Tanpa BEJ untuk mempelajari lebih lanjut.

Felix Kling
sumber
11

Jika Anda menggunakan TypeScript, Anda akan melihat kesalahan seperti ini:

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

TypeScript tidak tahu itu CustomTagadalah nama tag HTML yang valid dan melemparkan kesalahan yang tidak membantu.

Untuk memperbaikinya, gunakan CustomTagsebagai keyof JSX.IntrinsicElements!

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

<CustomTag>Hello</CustomTag>
Jack Steam
sumber
Saya menggunakan TypeScript tetapi casting memberikan kesalahan ini: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'.
Can Poyrazoğlu
8

Semua jawaban lain berfungsi dengan baik tetapi saya akan menambahkan beberapa tambahan, karena dengan melakukan ini:

  1. Ini sedikit lebih aman. Bahkan jika pengecekan tipe Anda gagal, Anda masih mengembalikan komponen yang tepat.
  2. Itu lebih deklaratif. Siapa pun dengan melihat komponen ini dapat melihat apa yang dapat dikembalikan.
  3. Misalnya, lebih fleksibel daripada 'h1', 'h2', ... untuk jenis Heading Anda, Anda dapat memiliki beberapa konsep abstrak lainnya 'sm', 'lg' atau 'primer', 'sekunder'

Komponen Tajuk:

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;

Yang dapat Anda gunakan seperti itu

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

atau Anda dapat memiliki konsep abstrak yang berbeda, misalnya Anda dapat menentukan ukuran alat peraga seperti:

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;

Yang dapat Anda gunakan seperti itu

<Heading size="sm">Some Heading</Heading>
Saman Shafigh
sumber
2

Dalam contoh heading dinamis (h1, h2 ...) , komponen dapat kembali React.createElement(disebutkan di atas oleh Felix ) seperti itu.

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

Untuk kompabilitas, baik alat peraga dan anak-anak dilewatkan

Lihat Contoh

robstarbuck
sumber