React - Как передавать HTML-теги в реквизитах?

118

Я хочу иметь возможность передавать текст с помощью тегов HTML, например:

<MyComponent text="This is <strong>not</strong> working." />

Но внутри MyComponentметода render, когда я распечатываю this.props.text, он буквально выводит все:

This is <strong>not</strong> working.

Есть ли способ заставить React анализировать HTML и правильно его выгружать?

ffxsam
источник
Какова ваша фактическая функция рендеринга?
Lucio
3
Типичным шаблоном было бы сделать ваш контент дочерним по отношению к вашему компоненту <MyComponent>This is <strong>not</strong> working</MyComponent>, а не передавать их как свойства. Не могли бы вы подробнее рассказать о том, чего вы на самом деле пытаетесь достичь?
Ник Томлин
Практически тот же вопрос: Reactjs конвертирует в html .
totymedli

Ответы:

140

Вы можете использовать смешанные массивы со строками и элементами JSX (см. Документацию здесь ):

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />

Здесь есть скрипка, которая показывает, что она работает: http://jsfiddle.net/7s7dee6L/

Кроме того, в крайнем случае у вас всегда есть возможность вставить необработанный HTML, но будьте осторожны, потому что это может открыть вас для атаки межсайтового скриптинга (XSS), если не очистить значения свойств.

matagus
источник
10
Это работает, за исключением того, что теперь я получаю предупреждение: Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную «ключевую» опору. Проверьте метод рендеринга CTA. Его передал потомок от Template1. См. Fb.me/react-warning-keys для получения дополнительной информации.
ffxsam
3
Вы можете избавиться от этой ошибки, пройдя через массив и добавив индекс в качестве ключа в MyComponent. {text.map( textOrHTML, index) => <span key={index}>{textOrHTML}</span> )} Хотя это так странно, что мы должны сделать это в первую очередь полностью.
HussienK 06
5
Вы можете также установить предупреждение, поставив key="[some unique value]"на <strong>элемент.
Чад Джонсон,
Отлично, работает нормально, я хотел бы знать, как я могу использовать переменную внутри strong вместо строки 'not'
Джейсон
3
Чтобы удалить предупреждение о ключах массива, теперь также можно передать один JSX, подобный этому. <MyComponent text={<>This is <strong>not</strong> working.</>} />
Ариф,
111

На самом деле, есть несколько способов добиться этого.

Вы хотите использовать JSX в своем реквизите

Вы можете просто использовать {}, чтобы JSX проанализировал параметр. Единственное ограничение такое же, как и для каждого элемента JSX: он должен возвращать только один корневой элемент.

myProp={<div><SomeComponent>Some String</div>}

Лучший читаемый способ сделать это - создать функцию renderMyProp, которая будет возвращать компоненты JSX (точно так же, как стандартная функция рендеринга), а затем просто вызвать myProp = {this.renderMyProp ()}

Вы хотите передать только HTML в виде строки

По умолчанию JSX не позволяет отображать необработанный HTML из строковых значений. Однако есть способ добиться этого:

myProp="<div>This is some html</div>"

Затем в своем компоненте вы можете использовать его так:

<div dangerouslySetInnerHTML=myProp={{ __html: this.renderMyProp() }}></div>

Помните, что это решение «может» открываться при атаках подделки межсайтовых сценариев. Также имейте в виду, что вы можете отображать только простой HTML, без тегов JSX, компонентов или других причудливых вещей.

Путь массива

В ответ вы можете передать массив элементов JSX. Это значит:

myProp={["This is html", <span>Some other</span>, "and again some other"]}

Я бы не рекомендовал этот метод, потому что:

  • Будет создано предупреждение (отсутствующие ключи)
  • Это не читается
  • Это не совсем способ JSX, это скорее взлом, чем задуманный дизайн.

Детский путь

Добавив его для полноты картины, но в качестве реакции, вы также можете получить всех дочерних элементов, находящихся «внутри» вашего компонента.

Итак, если я возьму следующий код:

<SomeComponent>
    <div>Some content</div>
    <div>Some content</div>
</SomeComponent>

Тогда два div будут доступны как this.props.children в SomeComponent и могут быть отображены с использованием стандартного синтаксиса {}.

Это решение идеально, если у вас есть только один HTML-контент для передачи вашему компоненту (представьте себе компонент Popin, который принимает только содержимое Popin в качестве дочерних).

Однако, если у вас есть несколько содержимого, вы не можете использовать дочерние элементы (или вам нужно хотя бы объединить его с другим решением здесь)

Atrakeur
источник
1
this.props.childrens - но this.props.children. Без 's' reactjs.org/docs/glossary.html#propschildren
Alexiuscrow,
13

Вы можете использовать опасноSetInnerHTML

Просто отправьте html как обычную строку

<MyComponent text="This is <strong>not</strong> working." />

И отрендерить в JSX-коде вот так:

<h2 className="header-title-right wow fadeInRight"
    dangerouslySetInnerHTML={{__html: props.text}} />

Просто будьте осторожны, если вы визуализируете данные, введенные пользователем. Вы можете стать жертвой XSS-атаки

Вот документация: https://facebook.github.io/react/tips/dangerously-set-inner-html.html.

hecontreraso
источник
7
<MyComponent text={<span>This is <strong>not</strong> working.</span>} />

а затем в своем компоненте вы можете выполнить проверку опоры следующим образом:

import React from 'react';
export default class MyComponent extends React.Component {
  static get propTypes() {
    return {
      text: React.PropTypes.object, // if you always want react components
      text: React.PropTypes.any, // if you want both text or react components
    }
  }
}

Убедитесь, что вы выбрали только один тип опоры.


источник
6

Для меня это сработало, передав тег html в props children

<MyComponent>This is <strong>not</strong> working.</MyComponent>


var MyComponent = React.createClass({

   render: function() {
    return (
      <div>this.props.children</div>
    );
   },
Shashi3456643
источник
6

В приложении реакции на стороне клиента есть несколько способов отрисовки опоры в виде строки с некоторым HTML. Один безопаснее другого ...

1 - Определите опору как jsx (мое предпочтение)

const someProps = {
  greeting: {<div>Hello<a href="/${name_profile}">${name_profile}</a></div>}
}


const GreetingComopnent = props => (
  <p>{props.someProps.greeting}</p>
)

• Единственное требование здесь заключается в том, что любой файл, генерирующий эту опору, должен включать React в качестве зависимости (в случае, если вы генерируете jsx опоры во вспомогательном файле и т. Д.).

2 - Опасно установить innerHtml

const someProps = {
  greeting: '<React.Fragment>Hello<a href="https://stackoverflow.com/${name_profile}">${name_profile}</a></React.Fragment>'
}

const GreetingComponent = props => {
  const innerHtml = { __html: props.someProps.greeting }
  return <p dangerouslySetInnerHtml={innerHtml}></p>
}

• Этот второй подход не рекомендуется. Представьте себе поле ввода, входное значение которого отображается как опора в этом компоненте. Пользователь может ввести тег сценария во входные данные, и компонент, который отображает эти входные данные, будет выполнять этот потенциально вредоносный код. Таким образом, такой подход может привести к уязвимости межсайтового скриптинга. Для получения дополнительной информации обратитесь к официальной документации React.

Виджей Селван Рам
источник
4

Установите любой тип опоры для текста и сделайте следующее:

<MyComponent text={
    <React.Fragment>
        <div> Hello, World!</div>
    </React.Fragment>
    } 
/>

пример

Амей Парундекар
источник
3

Вы можете сделать это двумя известными мне способами.

1- <MyComponent text={<p>This is <strong>not</strong> working.</p>} />

А потом сделай это

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.text}</div>)
   }
}

Или второй подход, сделайте это так

2- <MyComponent><p>This is <strong>not</strong> working.</p><MyComponent/>

А потом сделай это

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.children}</div>)
   }
}
Адил Имран
источник
1
Я добавил переменную let vhtml = "<p>Test</p>"и использовал ее в опоре вот так, text={vhtml}и по какой-то причине она все еще отображается в виде обычного текста.
Si8
2

Ответ @matagus подходит для меня, Надеюсь, что приведенный ниже фрагмент поможет тем, кто хочет использовать переменную внутри.

const myVar = 'not';
<MyComponent text={["This is ", <strong>{`${myVar}`}</strong>,  "working."]} />
Jaison
источник
1

В моем проекте мне пришлось передать динамический фрагмент html из переменной и отобразить его внутри компонента. Итак, я сделал следующее.

defaultSelection : {
    innerHtml: {__html: '<strong>some text</strong>'}
}

объект defaultSelection передается компоненту из .jsфайла

<HtmlSnippet innerHtml={defaultSelection.innerHtml} />

Компонент HtmlSnippet

var HtmlSnippet = React.createClass({
  render: function() {
    return (
      <span dangerouslySetInnerHTML={this.props.innerHtml}></span>
    );
  }
});

Пример Plunkr

реагировать на документ для опасногоSetInnerHTML

Раджкишор Саху
источник
1

Вы также можете использовать функцию в компоненте для передачи jsx через props. лайк:

 var MyComponent = React.createClass({

   render: function() {
    return (
      <OtherComponent
        body={this.body}
      />
    );
   },

   body() {
     return(
       <p>This is <strong>now</strong> working.<p>
     );
   }

});

var OtherComponent = React.createClass({

  propTypes: {
    body: React.PropTypes.func
  },

  render: function() {
     return (
        <section>
          {this.props.body()}
        </section>
     );
  },

});
Allison
источник
1

Да, вы можете это сделать, используя массив смешивания со строками и элементами JSX. ссылка

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />
Усама Бари
источник
1

Парсер от html-react-parser - хорошее решение. Тебе просто нужно

  • установите его с помощью npm или пряжи
  • импортировать парсер из 'html-response-parser';
  • назовите это с:

    <MyComponent text=Parser("This is <strong>not</strong> working.") />

    и это хорошо работает.

Franck212
источник
1

Дополнение к ответу: если вы собираетесь анализировать и уже используете JSX, но имеете объект с вложенными свойствами, очень элегантным способом является использование круглых скобок для принудительного анализа JSX:

const TestPage = () => (
  <Fragment>
    <MyComponent property={
    {
      html: (
        <p>This is a <a href='#'>test</a> text!</p>
      )
    }}>
    </MyComponent>
  </Fragment>
);
Ник Л.
источник
1

На этот вопрос уже есть много ответов, но я делал что-то не так в связи с этим, и я думаю, что стоит поделиться:

У меня было примерно так:

export default function Features() {
  return (
    <Section message={<p>This is <strong>working</strong>.</p>} />
  }
}

но массаж был более продолжительным, поэтому я попробовал использовать что-то вроде этого:

const message = () => <p>This longer message is <strong>not</strong> working.</p>;

export default function Features() {
  return (
    <Section message={message} />
  }
}

Мне потребовалось некоторое время, чтобы понять, что мне не хватает () в вызове функции.

Не работает

<Section message={message} />

Работает

<Section message={message()} />

может быть, это поможет тебе, как и мне!

Авраам Эрнандес
источник
1

Вы можете успешно использовать для этой задачи фрагменты React . В зависимости от React используемой версии, вы можете использовать короткий синтаксис: <>или полный тег: <React.Fragment>. Особенно хорошо работает, если вы не хотите заключать всю строку в теги HTML.

<MyComponent text={<>Hello World. <u>Don't be so ruthless</u>.</>} />
циклон
источник
0

Таким образом мы можем сделать то же самое.

const Child = () => {
  return (
     write your whole HTML here.
  )
}

теперь вы хотите отправить этот HTML-код внутри другого компонента, имя которого - родительский компонент.

Звонок: -

<Parent child={<child/>} >
</Parent> 

Использование ребенка: -

 const Parent = (props) => {
   const { child } = props; 
   return (
       {child}
    )
}

эта работа идеально подходит для меня.

pushparmar
источник
-9

Добавили html в componentDidMount с помощью jQuery append. Это должно решить проблему.

 var MyComponent = React.createClass({
    render: function() {

        return (
           <div>

           </div>
        );
    },
    componentDidMount() {
        $(ReactDOM.findDOMNode(this)).append(this.props.text);
    }
});
Кошик
источник
5
Это отклонено, потому что вы не должны использовать прямую манипуляцию с DOM jquery в сочетании с косвенными манипуляциями с DOM response, поскольку это может привести к сбоям в работе браузера.
Allison