Как объединить два фрагмента JSX или переменные или строку и компонент (в Reactjs)?

Я знаю, что JSX может быть очень вводящим в заблуждение, потому что он выглядит как строки, и это не так, поэтому термин "строка" в вопросе, даже если мы на самом деле не манипулируем строками.

Вот пример кода (неправильно, очевидно):

let line = <Line key={line.client_id} line={line}/>;
if(line.created_at) {
    return <div className="date-line"><strong>{line.created_at}</strong></div> + line;
} else {
    return chat_line;
}

У меня есть строка, и я хочу "конкатенировать" некоторые div перед ней при определенных условиях. Каким будет правильный синтаксис? Я пробовал скобки, скобки, плюс знак... Ни один из них, похоже, не работает...

спасибо

Ответ 1

Использовать массивы:

let lineComponent = <Line key={line.client_id} line={line}/>;
if (line.created_at) {
  return [
    <div key="date" className="date-line"><strong>{line.created_at}</strong></div>,
    lineComponent,
  ];
} else {
  return chat_line;
}

Или используйте фрагменты:

import createFragment from "react-addons-create-fragment";

let lineComponent = <Line key={line.client_id} line={line}/>;
if (line.created_at) {
  return createFragment({
    date: <div className="date-line"><strong>{line.created_at}</strong></div>,
    lineComponent: lineComponent,
  });
} else {
  return chat_line;
}

В обоих случаях вы должны предоставить ключи для React. В случае массива вы устанавливаете ключ непосредственно на элементе. Что касается фрагментов, вы предоставляете пары ключ: element.

Примечание: При возврате из метода render вы можете возвращать только один элемент или NULL. Приведенные примеры недействительны в этом случае.

Ответ 2

Для React Native я предпочитаю эту технику:

  • pro: в отличие от метода массива вам не нужно искусственно создавать ключи
  • con: требует накладных расходов на содержащий элемент (например, Вид ниже)
jsx = <Text>first</Text>;
jsx = <View>{jsx}<Text>second</Text></View>;

Ответ 3

Вы можете использовать пустые теги, я имею в виду, <> и </>, когда вы просто не хотите никаких дополнительных Container-Element (например, <View>), как показано ниже:

  render() {
    return (
      <>
        <Text>First</Text>

        <Text>Second</Text>
      </>
    );
  }

Пример:

import React from 'react'
import { View, Text } from 'react-native'

import Reinput from 'reinput'

export default class ReinputWithHeader extends Reinput {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <>
        <View style={{backgroundColor: 'blue', flexDirection: 'row', alignSelf: 'stretch', height: 20}}>
          <Text>Blue Header</Text>
        </View>

        {super.render()}
      </>
    );
  }
}

Примечание: я проверил, и он работает на react-native тоже; см. также фрагменты.

Предварительный просмотр:

enter image description here

Ответ 4

Если вы согласны с использованием родительского объекта, такого как другой div, вы также можете сделать это следующим образом:

let line = <Line key={line.client_id} line={line}/>;
if(line.created_at) {
    return <div><div className="date-line"><strong>{line.created_at}</strong></div>{line}</div>;
} else {
    return chat_line;
}