简体   繁体   English

在片段内危险地反应SetInnerHTML

[英]React dangerouslySetInnerHTML Inside Fragment

I have a use-case where I need to format some text in React and also render HTML.我有一个用例,我需要在 React 中格式化一些文本并渲染 HTML。

Here is an example of what I'm currently trying to achieve:这是我目前正在努力实现的一个例子:

import React, {Fragment} from "react";
import {renderToString} from "react-dom/server";

function FormatText(props) {
  const lines = props.children.split('\n');

  return lines.map((line, index) => (
    <Fragment key={index}>
      {line}{index !== lines.length - 1 && <br/>}
    </Fragment>
  ));
}

const content = {
  first: 'This is some text\nwith new\n\nline characters - 1',
  second: 'This is some text\nwith new\n\nline <strong>characters - <sup>2</sup></strong>',
};

function App() {
  return (
    <ol>
      <li>
        <FormatText>{content.first}</FormatText>
      </li>
      <li dangerouslySetInnerHTML={{
        __html: renderToString(<FormatText>{content.second}</FormatText>)
      }}/>
    </ol>
  )
}

As you can see, I have some content which contains \\n characters and HTML.正如你所看到的,我有一些content包含\\n字符和HTML。 Calling the renderToString function converts the HTML into encoded characters, which means the HTML is not rendered properly.调用renderToString函数会将 HTML 转换为编码字符,这意味着 HTML 未正确呈现。

Is there a way to render HTML inside a react fragment.有没有办法在反应片段中呈现 HTML。

Ideally I wanted to do the following (but it doesn't):理想情况下,我想做以下事情(但不是):

function FormatText(props) {
  const lines = props.children.split('\n');

  return lines.map((line, index) => (
    <Fragment key={index} dangerouslySetInnerHTML={{__html: renderToString(
        <Fragment>
          {line}{index !== lines.length - 1 && <br/>}
        </Fragment>
      )}}>
    </Fragment>
  ));
}
  • <Fragment> doesn't adds any node to DOM and so you can't do dangerouslySetInnerHTML on it . <Fragment>不会向 DOM 添加任何节点,因此you can't do dangerouslySetInnerHTML on it It is basically a functionality provided by React to avoid addition of extra node to DOM when you needed to return more than one from return in render.它基本上是 React 提供的一项功能,当您需要从渲染中的 return 返回多个节点时,它可以避免向 DOM 添加额外的节点。 So, if something doesn't exists on real DOM, you can't do anything on it .所以,如果真实的 DOM 上不存在某些东西,你就不能对它做任何事情
  • renderToString is generally used on node server. renderToString一般用在节点服务器上。 When doing server side rendering, you want to send the html from server to client.在进行服务器端渲染时,您希望将 html 从服务器发送到客户端。 So, better avoid renderToString also.所以,最好也避免renderToString

The issue is that, html doesn't recognises \\n for new line etc. It needs html tags.问题是,html 无法识别新行等的\\n 。它需要html标签。 The approach to use FormatText is fine or you can simply convert the \\n to br and then use dangerouslySetInnerHTML inside the <li> tag.使用FormatText方法很好,或者您可以简单地convert the \\n to br ,然后在<li>标签内使用危险的<li>

 const content = { first: 'This is some text\\nwith new\\n\\nline characters - 1', second: 'This is some text\\nwith new\\n\\nline <strong>characters - <sup>2</sup></strong>', }; function App() { return ( <ol> <li dangerouslySetInnerHTML={{ __html: content.first.replace(/\\n/g, "<br/>") }}/> <li dangerouslySetInnerHTML={{ __html: content.second.replace(/\\n/g, "<br/>") }}/> </ol> ) } ReactDOM.render(<App/>, document.getElementById("root"))
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script> <div id="root"></div>

Hope it helps.希望能帮助到你。 Revert for any doubts.如有任何疑问,请回复。

Hi I guess it is not possible, only way hot to pass formated html into DOm is via dom element DIV.嗨,我想这是不可能的,将格式化的 html 传递到 DOm 的唯一方法是通过 dom 元素 DIV。

Maybe this link could help you or point to https://reactjs.org/docs/dom-elements.html也许此链接可以帮助您或指向https://reactjs.org/docs/dom-elements.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM