Search code examples
reactjswordpressheadless-cms

Getting wordpress posts with react shows special chars instead of apostrophe


I am getting what I am assuming is json data from a wordpress blog endpoint like so:

https://example.com/wp-json/wp/v2/posts

I am looping through and showing the tiles for now:

<div>{posts && posts.map((post) => <h1>{post.title.rendered}</h1>)}</div>

But the post titles are not displaying properly. For example the word Don't shows Don&#8217;t

I have discovered that I can use dangerouslySetInnerHTML to fix this issue but is it safe? The fact that it has the word 'dangerously' in it is worrying.


Solution

  • I believe dangerouslySetInnerHTML is the way to go about this - but I will go into more detail as to why "dangerously" is in "dangerouslySetInnerHTML" and hopefully that will help you make an informed decision for your situation.


    What dangerouslySetInnerHTML does is render any HTML string given to it within the DOM element.

    For example:

    <h1 dangerouslySetInnerHTML={{__html: post.title.rendered}} />
    

    (as an aside, note the __html key has two underscores)

    Will properly render the string Don&#8217;t to Don't.

    This is all pretty harmless, however, if, for example, the value of post.title.rendered could be set by an untrusted party (such as an arbitrary user), and if this arbitrary user wanted to do some damage, they could enter a string such as:

    <script type="text/javascript>
    // Do evil stuff
    console.log('I did some evil stuff');
    </script>
    

    This code would then be executed by the browser when the page loads - because React would have generated the following DOM:

    <h1>
       <script type="text/javascript>
       // Do evil stuff
       console.log('I did some evil stuff');
       </script>
    </h1>
    

    So with all that in mind, if you are sure that the value of this field is within your control (and not anyone else's) and you also know that there will not be any arbitrary code in these strings, then go ahead and use dangerouslySetInnerHTML.

    However, if there is the possibility that someone besides yourself could manipulate this field, I would instead look to something like decode-html-entities - this way you can have the presentation you want, without compromising your app/users.