ชื่อแท็กแบบไดนามิกใน jsx และ React


163

ฉันพยายามเขียนองค์ประกอบ React สำหรับแท็กส่วนหัว html (h1, h2, h3, ฯลฯ ... ) ซึ่งลำดับความสำคัญหัวเรื่องเปลี่ยนแปลงแบบไดนามิกตามลำดับความสำคัญที่เราได้กำหนดไว้ในอุปกรณ์ประกอบฉาก

นี่คือสิ่งที่ฉันพยายามทำ

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

ผลลัพธ์ที่คาดหวัง:

<h1>Hello</h1>

สิ่งนี้ไม่ทำงาน มีวิธีใดที่เป็นไปได้ในการทำเช่นนี้?


คำตอบ:


329

ไม่มีวิธีการที่จะทำในสถานที่เพียงแค่ใส่ไว้ในตัวแปร ( ด้วยอักษรตัวใหญ่ตัวพิมพ์ใหญ่ ):

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

<CustomTag>Hello</CustomTag>

5
ง่ายกว่าแน่นอนReact.createClassฉันชอบวิธีนี้ ขอบคุณ
Vadorequest

@zerkms คุณมีความคิดวิธีเพิ่มแอตทริบิวต์ใน CustomTag หรือไม่? ขอบคุณ
Sabrina Luo

1
@Sabrina<CustomTag foo="bar">
zerkms

ฮะ. มันทำงานอย่างไร หากชื่อตัวแปรเป็นตัวพิมพ์เล็กก็แค่ใส่แท็กนั้น (เช่นถ้าเป็นแท็กที่กำหนดเองฉันจะได้รับ <customtag> Hello </customtag>) เอกสารนี้มีอยู่ทุกที่หรือไม่?
อิบราฮิม

5
ถ้าส่วนประกอบถูกเก็บไว้ในคุณสมบัติของวัตถุตัวอักษรตัวใหญ่ตัวแรกไม่จำเป็น var foo = { bar: CustomTag }; return <foo.bar />ทำงานได้ดี
jdunning

29

เพื่อความสมบูรณ์ถ้าคุณต้องการใช้ชื่อแบบไดนามิกคุณสามารถโทรได้โดยตรง React.createElementแทนที่จะใช้ JSX:

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

เพื่อหลีกเลี่ยงการสร้างตัวแปรหรือส่วนประกอบใหม่

ด้วยอุปกรณ์ประกอบฉาก:

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

จาก เอกสาร :

สร้างและส่งกลับองค์ประกอบปฏิกิริยาใหม่ของประเภทที่กำหนด อาร์กิวเมนต์ type สามารถเป็นสตริงชื่อแท็ก (เช่น'div'หรือ'span') หรือประเภทคอมโพเนนต์ React (คลาสหรือฟังก์ชัน)

รหัสเขียนด้วย JSX React.createElement()จะถูกแปลงการใช้งาน โดยทั่วไปคุณจะไม่เรียกใช้React.createElement()โดยตรงหากคุณใช้ JSX ดูReact Without JSXเพื่อเรียนรู้เพิ่มเติม


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>

ฉันใช้ TypeScript แต่กำลังส่งข้อผิดพลาดนี้: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

คำตอบอื่น ๆ ทั้งหมดทำงานได้ดี แต่ฉันจะเพิ่มพิเศษเพราะโดยทำสิ่งนี้:

  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(ดังกล่าวข้างต้นโดยเฟลิกซ์ ) เช่นนั้น

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

สำหรับการจัดองค์ประกอบทั้งอุปกรณ์และเด็กจะถูกส่งผ่าน

ดูตัวอย่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.