Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use dangerouslySetInnerHTML without the wrapper div?

Tags:

reactjs

gatsby

My HTML content is coming from an API (Gatsby in this case) so I'm using dangerouslySetInnerHTML as recommended. The thing is, it messes with my styling, specifically with grids. I have a html markup like this:

<article>
    <h2>Title of the post<h2>
    <small>Date of the post</small>
    <div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>

This <article> tag contains a display: grid style. But all the content inside that div is taking precious space making it hard to style (also it's not an useful div!). All the important html is inside but I want to get rid of the actual <div> tag. Is there any way to do it?

Note: I already tried to {post.html} it directly but it's encodedURI which can't be decoded.

Thank you!

like image 703
Rafael 'BSIDES' Pereira Avatar asked Dec 08 '18 12:12

Rafael 'BSIDES' Pereira


2 Answers

Check out the react docs for dangerouslySetInnerHTML.

you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key...

So there's nothing stopping you from forming your own html string from different parts of your graphql query like so:

const createFullPostMarkup = () => {
    return { __html: `<h2>Title of the post</h2><small>Date of the post</small>${ post.html }` }
}

And then setting it later as inner html on your article like this:

<article dangerouslySetInnerHTML={createFullPostMarkup()} />

Remember, this is just an object with a __html key. You can put anything in there.

Note: What I think you might be after is described by this open feature request. For your use case, i think the above solution works perfectly. But if you're still not satisfied, check out the discussion in the linked issue.

like image 71
ksav Avatar answered Sep 18 '22 22:09

ksav


You can also do this:

/**
 * Load CSS file in parallel vs a blocking <link /> tag
 *
 * @param {string} fontUrl The raw font URL
 */
const LoadCSSFile = ({ fontUrl }) => {
  // hilariously bad hack to get around React's forced wrapper for dangerouslySetInnerHTML
  // @see https://github.com/facebook/react/issues/12014#issuecomment-434534770
  let linkStr = '</style>';
  linkStr += `<link rel="preload" href="${fontUrl}" as="style" onload="this.rel='stylesheet'" />`;
  linkStr += `<noscript><link rel="stylesheet" href="${fontUrl}"></noscript>`;
  linkStr += '<style>';

  return <style dangerouslySetInnerHTML={{ __html: linkStr }} />;
};

This will output as:

<style></style>
<link ... />
<noscript><link ... /></noscript>
<style></style>

Definitely not the most elegant solution but it should accomplish what you need until React supports dangerouslySetInnerHTML on fragments.

like image 36
Scott L Avatar answered Sep 19 '22 22:09

Scott L