Using Fragment to insert HTML rendered on the back end via dangerouslySetInnerHTML

拈花ヽ惹草 提交于 2021-02-18 06:34:24

问题


I used to compile and insert JSX components via

<div key={ ID } dangerouslySetInnerHTML={ { __html: HTML } } />

which wrapped my HTML into a <div>:

<div>my html from the HTML object</div>

Now react > 16.2.0 has support for Fragments and I wonder if I can use that somehow to avoid wrapping my HTML in a <div> each time I get data from the back end.

Running

<Fragment key={ ID } dangerouslySetInnerHTML={ { __html: HTML } } />

will throw a warning

Warning: Invalid prop `dangerouslySetInnerHTML` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.
in React.Fragment

Is this supported yet at all? Is there another way to solve this?

Update

Created an issue in the react repo for it if you want to upvote it.


回答1:


Short Answer

Not possible:

key is the only attribute that can be passed to Fragment. In the future, we may add support for additional attributes, such as event handlers.

https://reactjs.org/docs/fragments.html

You may want to chime in and suggest this as a future addition.

https://github.com/facebook/react/issues

In the Meantime

You may want to consider using an HTML parsing library like:

https://github.com/remarkablemark/html-react-parser

Check out this example to see how it will accomplish your goal:

http://remarkablemark.org/blog/2016/10/07/dangerously-set-innerhtml-alternative/

In Short

You'll be able to do this:

<>
{require('html-react-parser')(
    '<em>foo</em>'
)}
</>



回答2:


Update December 2020

This issue (also mentioned by OP) was closed on Oct 2, 2019. - However, stemming from the original issue, it seems a RawHTML component has entered the RFC process but has not reached production, and has no set timeline for when a working solution may be available.

That being said, I would now like to allude to a solution I currently use to get around this issue.

In my case, dangerouslySetInnerHTML was utilized to render plain HTML for a user to download; it was not ideal to have additional wrapper tags included in the output.

After reading around the web and StackOverflow, it seemed most solutions mentioned using an external library like html-react-parser.

For this use-case, html-react-parser would not suffice because it converts HTML strings to React element(s). Meaning, it would strip all HTML that wasn't standard JSX.


Solution:

The code below is the no library solution I opted to use:

//HTML that will be set using dangerouslySetInnerHTML
const html = `<div>This is a div</div>`

The wrapper div within the RawHtml component is purposely named "unwanteddiv".

//Component that will return our dangerouslySetInnerHTML
//Note that we are using "unwanteddiv" as a wrapper
    const RawHtml = () => {
        return (
            <unwanteddiv key={[]}
                dangerouslySetInnerHTML={{
                    __html: html,
                }}
            />
        );
    };

For the purpose of this example, we will use renderToStaticMarkup.

const staticHtml = ReactDomServer.renderToStaticMarkup(
<RawHtml/>
);

The ParseStaticHtml function is where the magic happens, here you will see why we named the wrapper div "unwanteddiv".

  //The ParseStaticHtml function will check the staticHtml 
  //If the staticHtml type is 'string' 
  //We will remove "<unwanteddiv/>" leaving us with only the desired output
    const ParseStaticHtml = (html) => {
        if (typeof html === 'string') {
            return html.replace(/<unwanteddiv>/g, '').replace(/<\/unwanteddiv>/g, '');
        } else {
            return html;
        }
  };

Now, if we pass the staticHtml through the ParseStaticHtml function you will see the desired output without the additional wrapper div:

  console.log(ParseStaticHtml(staticHtml));

Additionally, I have created a codesandbox example that shows this in action.

Notice, the console log will throw a warning: "The tag <unwanteddiv> is unrecognized in this browser..." - However, this is fine because we intentionally gave it a unique name so we can easily differentiate and target the wrapper with our replace method and essentially remove it before output.

Besides, receiving a mild scolding from a code linter is not as bad as adding more dependencies for something that should be more simply implemented.



来源:https://stackoverflow.com/questions/48236588/using-fragment-to-insert-html-rendered-on-the-back-end-via-dangerouslysetinnerht

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!