How to use external templates for ReactJS? - reactjs

I am learning ReactJS and in ALL examples that I see on the web the HTML code is always rendered inline, meaning that you have to add all HTML markup directly into the JS file which is super ugly and very hard to work with (if you have a lot of markup). IsnĀ“t there a way to put all HTML in a separate file just referens that file when rendering? Like we do in Rails or Angular 2.
This is my code:
var Main = React.createClass({
render() {
return (
<div> <h1>Hello, World!</h1> </div>
)
}
});
I want to put this in a separate file:
<div> <h1>Hello, World!</h1> </div>

You can put your html in a separate .js file and import it in your component then use,
htmlMarkup.js
module.exports = `<div> <h1>Hello, World!</h1> </div>`;
and then in your component
render() {
return (<div dangerouslySetInnerHTML={require('path/to/htmlMarkup.js')} />)
}
if you want to set some property in your html file, then you can export a function instead of string.
module.exports = (message) => `<div> <h1>${message}</h1> </div>`;
and then in render method.
render() {
return (<div dangerouslySetInnerHTML={require('path/to/htmlMarkup.js')('Hello World')} />)
}

Related

How to render React template in string as DOM using NextJS?

I have some template which use React Component e.g:
<Section>
<div>
<HelloWorld />
</div>
<Hello name="my name" />
</Section>
and some components defined in my code such as :
export function Section({children}) {
return <div className="custom-class">{children}</div>
}
export function HelloWorld() {
return <div>Hello World</div>
}
export function Hello({name}) {
return <div>Hello {name}</div>
}
I would like to pass the template (as a string) to react and make it generate the correct DOM using the components I declared in my codebase. How can I do this ?
I tried using the props dangerouslySetInnerHTML but it only read raw html.
I also looked at next-mdx-remote https://github.com/hashicorp/next-mdx-remote which is almost what I need but for mdx.
Is there a straight solution or a library that exist who solve this issue ?

Custom namespaced attribute in JSX/React

As I already figured out, React's JSX doesn't support namespace tags by default. But lets say I have the following component:
render() {
return (
<div><!-- This should contain th:text -->
...
</div>
);
}
and I want this component to be rendered to:
<div th:text="value">
...
</div>
How can I achieve, that th:text="value" will be added to the rendered output?
Found the solution a few minutes later:
const i18n = {
"th:text": "${#foo.bar}"
};
render() {
return (
<div {...i18n}>
...
</div>
);
}

How can i pass a pirce of HTML content into a stateless react component?

I want to make a simple React component that wraps the given HTML content into a tag that serves as a context in which the content is displayed.
function Content(content) {
return <div>{content}</div>;
}
<Content>
<span>Hey!</span>
</Content>
What am i doing wrong?
function Content(props) {
return <div>{props.children}</div>;
}
Using ES6 syntax:
const Content = ({ children }) => <div>{children}</div>
Simple React component that wraps the given HTML content.
var content = "<Content><span>Hey!</span></Content>"
function Content() {
return (
<div className="content" dangerouslySetInnerHTML={{__html:
content}}>
</div>
);
}

Implement HTML Entity Decode in react.js

I am outputting the text using API from the server, and I have an admin which has the html fields for facilitating filling the content. The issue in here that now the text displaying with html codes. How I can get rid of that undeeded html codes. I guess I have to use html entity decode? How I will implement that in react project? Below you see that the text illustrates not only text and html code.
export class FullInfoMedia extends React.Component {
render() {
const renderHTML = (escapedHTML: string) => React.createElement("div", { dangerouslySetInnerHTML: { __html: escapedHTML } });
return (
<div>
<div className="about-title">
<div className="container">
<div className="row">
<img className="center-block" src={this.props.about.image}/>
<h2>{this.props.about.title}</h2>
{renderHTML(<p>{this.props.about.body}</p>)}
</div>
</div>
</div>
</div>
);
}
}
You can use dangerouslySetInnerHTML, but be sure you render only your input, not users. It can be great way to XSS.
Example of using:
const renderHTML = (rawHTML: string) => React.createElement("div", { dangerouslySetInnerHTML: { __html: rawHTML } });
And then in a component:
{renderHTML("<p>&nbsp;</p>")}
Even though you can use dangerouslySetInnerHTML it's not really a good practice, and as stated by Marek Dorda it's a great thing for making your app XSS vulnerable.
A better solution would be to use the he library. https://github.com/mathiasbynens/he
This would be an example of how would your component look with it.
import he from 'he'
export class FullInfoMedia extends React.Component {
render() {
const renderHTML = (escapedHTML: string) => React.createElement("div", { dangerouslySetInnerHTML: { __html: escapedHTML } });
return (
<div>
<div className="about-title">
<div className="container">
<div className="row">
<img className="center-block" src={this.props.about.image}/>
<h2>{this.props.about.title}</h2>
{ he.decode(this.props.about.body) }
</div>
</div>
</div>
</div>
);
}
}
Also, if it were my codebase, I would most likely move the decoding to the API call, and in the component just consume the value that comes from the store
You can simply try this, it decodes text and then display.
<p dangerouslySetInnerHTML={{__html:"&nbsp;"}}/>

Do I have to wrap components in html tags?

I've seen the pattern that components always seem to be wrapped in HTML tags.
I've searched the docs to check if this is mandatory, but not found anything on the topic.
If the above isn't true, why do I get an error on the first code example and not on the second?
const App = (props) => {
return (
<Header />
{props.children}
);
};
const App = (props) => {
return (
<div>
<Header />
{props.children}
</div>
);
};
Nope, it's not required to wrap your render in a div or other html element specifically, you can render using a Component as the root element. You cannot however have more than one root element, that is why you are getting an error in the first example. The following would work however:
render() {
<Header>
<h1>Hello World</h1>
<p>Lorem ipsum</p>
</Header>
}
In the end you will still likely have to have some sort of wrapper div within the Header component as you cannot have more than 1 root element.
I did read somewhere that the React team are looking into this, and that the new reconciler supports multiple root elements, however it is far from finished.
You don't have to wrap them specifically in HTML tags. You could wrap them in a custom component instead.
The error you're getting is because a component has to return a single node, which is why you can't do this:
// WRONG
const App = (props) => {
return (
<Header />
{props.children}
);
};

Resources