Как использовать компонент <Link /> внутри опасно SetInnerHTML - PullRequest
0 голосов
/ 25 января 2019

В настоящее время у меня есть это в одном из моих компонентов:

{someObject.map(obj => (
    <div
        dangerouslySetInnerHTML={{
            __html: obj.text
        }}
    />
))}

По сути, я сопоставляю someObject, что в другом файле.Структура выглядит следующим образом:

export default someObject = [
      {
         obj: "<p>Some text 1.</p>"
      },
      {
         obj: "<p>Some text 2.</p>"
      }
    ]

Я просто упрощаю контент для демонстрации.Однако я столкнулся с проблемой, потому что мне нужно использовать компонент <Link /> в одном из элементов.Как в:

export default someObject = [
    {
        obj: "<p>Some text 1.</p>"
    },
    {
        obj: "<p>Some text 2.</p>"
    },
    {
        obj: "<p>Some text 2 and <Link to="/someroute">link</Link>.</p>"
    }
]

Однако, это не работает, потому что весь тег <p></p> обернут в dangerouslySetInnerHTML.

Я могу просто использовать простой тег <a></a> для ссылки, ноэто не кажется хорошим решением, поскольку все приложение будет перезагружаться вместо того, чтобы просто идти по другому маршруту.

Какие есть другие варианты, чтобы эта работа работала?

Ответы [ 3 ]

0 голосов
/ 25 января 2019
  • Существует два способа решения этой проблемы:

Первый путь:

это как более общий подход, вы можете использовать его для выбора своего кода. попробуйте использовать эту библиотеку (https://github.com/tasti/react-linkify/)

Вот более простая форма компонента:

import React, {PropTypes} from 'react';
import Linkify from 'react-linkify';

export default class TextWithLink extends React.Component {
    constructor(props) {
      super(props);
    }

    render() {
      let text = this.props.text;
      if(this.props.showLink) {
        text = <Linkify properties={{target: '_blank', rel: "nofollow   noopener"}}>{text}</Linkify>
      }
      return (<div>{text}</div>);
    }
}

Второй способ:

В случае, если вы хотите создать гиперссылку (<a>), у вас должна быть функция, которая создает элементы и возвращает результат.

Пример:

list = {
  text: 'hello world',
  link: 'www.facebook.com'
}

И функция рендеринга может выглядеть примерно так:

buildLink() {
   return(
      <p>
        {list.text}. <a href={list.link}>{list.link}</a>
      </p>
    );
}

render() {
   return (this.buildLink());
}
0 голосов
/ 25 января 2019

Почему бы вам просто не экспортировать объект как объект jsx? Я думаю, что использование dangerouslySetInnerHTML - плохая практика, это может вызвать атаку XSS.

const someObject = [
  {
    obj: <p>Some text 1.</p>
  },
  {
    obj: <p>Some text 2.<a href="https://google.com">google</a></p>
  }
]
class App extends React.Component {
  render(){ 
    return (
    <div className="App">
      <h1>Hello world</h1>
      <h2>Jsx object goes here {someObject[1].obj}</h2>
    </div>
  )};
}

const rootElement = document.getElementById("container");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>
0 голосов
/ 25 января 2019
export default someObject = [
    {
        obj: "<p>Some text 1.</p>"
    },
    {
        obj: "<p>Some text 2.</p>"
    },
    {
        obj: linkto('/someroute')
    }
]

linkto решит вашу проблему.

...