How to render a template string as HTML? - reactjs

Let's say I have a simple template string :
const foo = `<div>foo</div>`;
How do I go about rendering this template string as HTML ?
It renders it as plain text if I do the following :
return({ foo });
Output:
<div>foo</div>
Expected output:
foo

I think what you try to do is
const foo = `<div>foo</div>`;
<div dangerouslySetInnerHTML={{ __html: foo }}></div>
Related question.
React documentation.

You note reactjs as a tag here. Instead of specifying the html as a string, make foo a functional react component.
To do that, make sure you have import React as 'react';.
Then, set foo as the functional component, i.e.:
const foo = () => <div>foo</div>;
Then, you can use that wherever you please. React components are just functions (or classes) that return jsx.
Your question is fairly open-ended, so you may be looking for some of the above answers, but this is one approach.

Off the top of my head there's 2 ways to parse a string (doesn't have to be a tl) into HTML: .innerHTML property and the more powerful .insertAdjacentHTML() method.
Demo
var tl = `
<video src='http://media6000.dropshots.com/photos/1381926/20170326/005611.mp4' controls width='320'></video>`;
document.body.innerHTML = tl;
document.body.insertAdjacentHTML('afterbegin', tl);

if you want to show the string of html as html page its better to do this:
<text>{{ info | safe }}</text>

Related

I want to write other languages code in react js

I am working on building a website.
I made all things, but now I'm stuck in adding code to the website.
I want to put some codes inside the JSX component but it is having some problems with adding { <<these types of symbols.
Is there any way I can write the C++ code or C code inside the react element?
import React from 'react'
const Template = () => {
return (
<div>
<h1></h1>
</div>
)
}
export default Template
The JSX won't appreciate the "{ <<", but if you want a quick in on this, you may try something like this -
const SomeCode = ()=><code>{`#include <stdio.h>;`}</code>
That might not be sufficient - you may need proper highlighting with specific programming language, formatting, etc. for what you might be building. But just for getting literals such as << working with JSX - you may take the above example as base.
In JSX, which is what react usees, brackets will be parsed.
Therefore, strings should be inside {`content`}, or you can define that code as a string, and place it inside jsx as below
const SomeComponent = ()=>{
const codeSnippet = `{ << whatever code blahblah`
return <div>
{codeSnippet}
</div>
}

Dynamic content inside Trans Component i18next

I have a list of translated keys and react component content.
e.g :
list = [{ translation: "Hello <1>World</1>", content: "Hello <a href='#'>World</a>" },
{ translation: "A <1>B</1>", content: "A <a href='#'>B</a>" }]
The idea is to show a translated data from the list using the "translation" and the structure of "content" with Trans Component of i18next-react with a map function.
{list.map((item) => (
<Trans i18nKey={item.translation}>
{item.content}
</Trans>))}
Unfortunately, this doesn't seem to work at all, the outcome is only the translated string, without the structure that should came by the React Component content.
Any idea how to work around this?
Your content is a pure string and not a react element. Therefore your code can't work -> it can't extract the a element from the string and replace the <1> with it.
edit below
sample:
{list.map((item) => (
<Trans
i18nKey={item.translation}
defaults={item.translation} // Hello <0>World</>
components={[World]}
</Trans>))}
You need to pass in the components to get interpolated into the "pseudo" tags <0>...details also have a look at https://react.i18next.com/misc/using-with-icu-format (for props defaults, components, values)
Just in case anyone will try to do this in the future:
The way to do so is to use components props as Jamuhl mentioned.
And to pass there an array with the HTML elements of the "item.content".
The way to get the array of HTML elements from a string as we have on "item.content" is by using ReactHtmlParser that parse that string into an HTML elements array!
ReactHtmlParser can be cloned from here: https://www.npmjs.com/package/react-html-parser
For who still have problem.
make sure you have correct order of nested html
like
key ="<0><0/><1>translated here</1></0>";
function createMarkup()
{
return <div><input type="checkbox" /><label>translate here</label></div>;
}
<Trans i18nKey="key" >{ReactHtmlParser(createMarkup())}</Trans>

Converting HTMLElement to a React Element, and keeping any event listeners

Rendering some JSON data into a set of collapsible HTML elements is EASY using a library like renderjson (npm package) for Vanilla JS
const data = { sample: [1, 2, 3, 4], data: { a: 1, b: 2, c: ["hello", null] } };
const rjson = renderjson(data);
document.getElementById('to-render').append(rjson);
In The react world
However, renderjson returns an HTMLElement, NOT A STRING. Please note that I'm not JUST trying to convert HTML strings into react HTML here. I'm trying to convert the HTMLElement into a real ReactElement.
So, I actually managed to do this, but since I'm parsing the HTMLElement into a string, all the onClick event listeners generated by renderjson on the + and - handles (to open or collapse the json) are LOST in the process....
Does anyone have any idea on how to convert a HTMLElement object into React Element, keeping all the original event handlers?
I guess, the real question here is: how can the renderjson package be "repackaged" to become React friendly?
Here is a codesandbox to make it easier to see what I'm talking about here.
Good question, I keep running into similar issues with non-React JS libraries that return DOM elements. These libraries should be ported to React, but if you don't want to do that, you can use findDomNode() to get a DOM (not React) node, and append your HTMLElement there. Please note that in the official docs, its use is discouraged because "it pierces the component abstraction". Anyways, in your example, you could add a wrapper class:
class JsonTreeWrapper extends Component {
componentDidMount() {
const renderedJson = renderjson(this.props.data);
const container = findDOMNode(this);
container.appendChild(renderedJson);
}
render() {
return <div/>;
}
}
what this does is render a div, and when the component mounts it finds the div and adds the HTMLElement generated by your library there. Simple.
In your App, you can use it like this:
class App extends Component {
render() {
return (
<div>
<h1> Inside the react world </h1>
<JsonTreeWrapper data={data}/>
</div>
);
}
}
This way your listeners will be working just fine.
Codesandbox didn't work for me, but you can check a demo here. I hope this helps!

How to render a HTML string in React?

I have a string like < b >hi< /b >. I have to render it as "hi". Can someone let me know an equivalent thing like innerHTML in Angular that I can use in React?
you can try dangerouslySetInnerHTML with the enclosing tag:
<div dangerouslySetInnerHTML={{ __html: yourhtml }} />
According to official React docs
dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it’s dangerous. For example:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
To avoid the potential security vulnerabilities (such as XSS attacks) that are present when using dangerouslySetInnerHTML, you can do the following:
First use DOMPurify to clean the HTML.
import DOMPurify from 'dompurify';
let clean = DOMPurify.sanitize(dirtyHtmlString, {USE_PROFILES: {html: true}});
Then it can be rendered using react-render-html as Salman Lone said:
import renderHTML from 'react-render-html';
<div>
{renderHTML(clean)}
</div>
in my case, I used following pacakge.
react-render-html
According to the website "https://reactjs.org/docs/dom-elements.html" you should use dangerouslySetInnerHTML in order to avoid cross-site scripting (XSS) attacks. However, if you are controlling the string that you want to render then that may not be necessary. If you wish to render HTML this way then as the above website explains, you may do so in this way:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
I personally do not like the dangerouslySetInnerHTML method (mostly because it has the word dangerous and that scares me). I cannot say if the next method is better, safer, faster etc but I like it much more. The second method that you can use is to render the HTML with useRef.
An example of this method is:
import React, {useRef, useEffect} from 'react'
export default function Example() {
const aRef = useRef()
const content = '<p style="color:red">hello</p><h1>world</h1>'
useEffect(()=>{
if(aRef==null)return
aRef.current.innerHTML = content
},[aRef, content])
return <div ref={aRef}/>
}
I forgot to do testing for setting class, id, ref, values etc via string.
If someone wants to add to this answer, please add examples for every React operation like I have done with style.

Interpolation with <Link> of react-router

I'm working with react-router, and actually what I want is very simple, so I won't be too long, is just to get a string with a <Link> of react-router interpolated like:
const link = (
<Link to={"/terms"}>{"terms"}</Link>
);
const label = (
`something ${link}`
);
Actual result:
something [object Object]
Expected result:
something terms
Anybody knows how do I get the expected result?
I ran into the same issue and couldn't find a way to evaluate the Link object toString, within an interpolation; however, I found a workaround as (based on your setup) you can pass in multiple nodes in JSX as props. As an example, you could do something like:
label={
<div>
<span>something</span>
<Link to={'/terms'}>terms of use</Link>
<span> and other terms and such</span>
</div>
}
The link could then evaluate to the string/html output you are looking to render. Hope this helps !
You can take a look at: https://www.npmjs.com/package/jsx-to-html
Otherwise, you can use jsx-transform package which will give you information regarding the props you are passing.
const linkString = jsx.fromString(link, { factory: 'mercury.h' });
console.log(linkString); // 'Link({to: "/terms"}, ["terms"])'
Then you can use regex:
const linkPath = eval(linkString.match(/{(.*?)}/)[0]); // '/terms'
const label = `Whatever`;

Resources