Tên thẻ động trong jsx và React


162

Tôi cố gắng viết một thành phần React. đối với các thẻ tiêu đề html (h1, h2, h3, v.v ...), trong đó mức độ ưu tiên của tiêu đề thay đổi linh hoạt dựa trên mức độ ưu tiên mà chúng ta đã xác định trong các đạo cụ.

Đây là những gì tôi cố gắng làm.

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

sản lượng dự kiến:

<h1>Hello</h1>

Đây không phải là làm việc. Có bất kỳ phương pháp có thể để làm điều này?


Câu trả lời:


328

Không có cách nào để làm điều đó tại chỗ, chỉ cần đặt nó vào một biến ( với chữ cái đầu tiên viết hoa ):

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

<CustomTag>Hello</CustomTag>

5
Chắc chắn dễ dàng hơn React.createClass, tôi thích cách này. Cảm ơn.
Vadorequest

@zerkms Bạn có biết làm thế nào để thêm thuộc tính vào CustomTag không? cảm ơn
Sabrina Luo

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

Huh. Cái này hoạt động ra sao? Nếu tên biến là chữ thường, nó chỉ chèn nó dưới dạng thẻ (ví dụ: nếu đó là customtag, tôi sẽ nhận được <customtag> Hello </ customtag>). Đây có phải là tài liệu ở bất cứ đâu?
Ibrahim

5
Nếu thành phần được lưu trữ trong tài sản của đối tượng, chữ cái viết hoa đầu tiên là không cần thiết. var foo = { bar: CustomTag }; return <foo.bar />hoạt động tốt
vui vẻ

29

Để hoàn thiện, nếu bạn muốn sử dụng tên động, bạn cũng có thể gọi trực tiếp React.createElementthay vì sử dụng JSX:

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

Điều này tránh phải tạo một biến hoặc thành phần mới.

Với đạo cụ:

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

Từ các tài liệu :

Tạo và trả về một phần tử React mới của loại đã cho. Đối số loại có thể là một chuỗi tên thẻ (chẳng hạn như 'div'hoặc 'span') hoặc loại thành phần React (một lớp hoặc một hàm).

Mã được viết bằng JSX sẽ được chuyển đổi để sử dụng React.createElement(). Thông thường, bạn sẽ không gọi React.createElement()trực tiếp nếu bạn đang sử dụng JSX. Xem React without JSX để tìm hiểu thêm.


11

Nếu bạn đang sử dụng TypeScript, bạn sẽ thấy một lỗi như thế này:

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

TypeScript không biết rằng CustomTag là một tên thẻ HTML hợp lệ và đưa ra một lỗi không có ích.

Để sửa, đúc CustomTagnhư keyof JSX.IntrinsicElements!

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

<CustomTag>Hello</CustomTag>

Tôi đang sử dụng TypeScript nhưng việc truyền tải nó sẽ gây ra lỗi này: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'.
Có thể Poyrazoğlu

8

Tất cả các câu trả lời khác đang hoạt động tốt nhưng tôi sẽ thêm một số, bởi vì làm điều này:

  1. Nó an toàn hơn một chút. Ngay cả khi việc kiểm tra kiểu của bạn không thành công, bạn vẫn trả về một thành phần thích hợp.
  2. Nó là tuyên bố nhiều hơn. Bất cứ ai bằng cách nhìn vào thành phần này có thể thấy những gì nó có thể trở lại.
  3. Ví dụ, nó linh hoạt hơn thay vì 'h1', 'h2', ... đối với loại Tiêu đề của bạn, bạn có thể có một số khái niệm trừu tượng khác 'sm', 'lg' hoặc 'chính', 'phụ'

Thành phần Heading:

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;

Mà bạn có thể sử dụng nó như thế nào

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

hoặc bạn có thể có một khái niệm trừu tượng khác, ví dụ bạn có thể định nghĩa một đạo cụ kích thước như:

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;

Mà bạn có thể sử dụng nó như thế nào

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

2

Trong trường hợp của các tiêu đề động (h1, h2 ...) , một thành phần có thể trả về React.createElement(được đề cập ở trên bởi Felix ) như vậy.

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

Đối với khả năng kết hợp, cả đạo cụ và trẻ em đều được thông qua.

Xem ví dụ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.