How to embed React Components in html pages - reactjs

I want build a React component like
class MyComponent extends React.Component {
render(){
return (<div>This is a simple component</div>);
}
}
and use it like
<MyComponent></MyComponent>
in several different pages and even multiple times in a single html page.
I dont want to create a SPA just to enhance my web application's UI with React components.

Use
ReactDOM.render(<MyComponent />, document.getElementById('id'));
You can render in your HTML like this:
<div id="id"></div>

What you are asking for is not possible right now with React, you want to use what is known as web components.
https://webdesign.tutsplus.com/articles/how-to-create-your-own-html-elements-with-web-components--cms-21524
Read this to learn how to.
The other method is obviously
ReactDOM.render(<MyComponent />, document.getElementById('id'));
If you have to stick with React.

In index.jsx change the typical search for element root getElementById and change the logic to a getElementsByTagName scheme.
let elements=document.getElementsByTagName('MyComponent');
for (element of elements){
ReactDOM.render( <MyComponent />, element );
}

Simply adding React components into HTML code is not possible, because <MyComponent></MyComponent> is not HTML at all, it is JSX.
Explaination
JSX is a special syntax that can be 'transpiled' to Javascript, so in essence <MyComponent></MyComponent> will end up beeing Javascript code, which obviously can not just be put into HTML code.
The Javascript code generated from JSX then will be executed and generates actual HTML code.
It is possible to add HTML tags into JSX, because HTML can be interpreted as JSX (and will be transpiled to Javascript as well), like:
class MyComponent extends React.Component {
render(){
return <div>
<h2>HTML in JSX works</h2>
<SomeOtherJsxComponent />
</div>;
}
}
But it is not possible to add JSX into HTML, like:
<body>
<div>
<JsxInHtmlDoesNotWork />
</div>
</body>
React is Javascript, so everything that is necessary to add Javascript functionality to HTML also applies to adding React to HTML.
(nearest) Solution
So what you could do is to move your existing HTML into to some JSX wrapper (which is probably not what you would like to do, because this goes in the direction of creating a SPA, what you don't want), e.g.:
<html><head>
<title>My web site</title>
</head><body>
<h1>Some HTML title</h1>
<p>Some HTML content.</p>
<!-- add a container, where you want to include react components -->
<div id="injected-react-content"></div>
<!-- import the react libraray -->
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<!-- setup react root component other components -->
<script type="text/babel">
class RootComponent extends React.Component {
render(){
return <div>
<MyComponent />
</div>;
}
}
class MyComponent extends React.Component {
render(){
return (<div>This is a simple component</div>);
}
}
const domContainer = document.querySelector('#injected-react-content');
ReactDOM.render( React.createElement(RootComponent), domContainer );
</script>
</body></html>
For some more background information on how to add React to an existing HTML website, see e.g.:
stackoverflow.com/questions/65917670/how-to-use-react-components-as-part-of-legacy-html-js-app
stackoverflow.com/questions/69607103/react-component-not-displayed-in-html

There are couple of options which can be explored here
parcel bundle
https://javascriptpros.com/creating-react-widgets-embedded-anywhere/
direflow bundle
https://jhinter.medium.com/using-react-based-web-components-in-wordpress-f0d4097aca38

Related

Mutiple ReactDOM.render functions?

I'm starting to learn react and getting a problem when calling multiple ReactDOM.render functions:
react:
class Header extends React.Component{
render(){
return(
<div>
<p>Test1</p>
</div>
)
}
};
class Main extends React.Component {
render(){
return(
<section>
<p>Test2</p>
</section>
)
}
};
ReactDOM.render(<Main />, document.getElementById('root2'));
ReactDOM.render(<Header />, document.getElementById('root'));
html part:
<body>
<div id="root"></div>
<div id="root2"></div>
</body>
I'm getting the error:
Target container is not a DOM element.
When searching for this problem I got the information that it should be possible to call ReactDom.render multiple times. So I appreciate your help!
Edit: Just tried it with one html tag and changed the id. It seems to have a problem when the id is not "root"...
You are right, you should be able to call render multiple times in your code.
But instead of doing that why don't you do this:
Class App extends Component {
render(){
<React.Fragment>
<Header />
<Main />
</React.Fragment>
}
}
ReactDOM.render(<App />, document.getElementById('root'))
This is easier, correct and performance superior.
I really see no reason as to why soomeone woudld need to put 2 different renderers on one page. Its just putting more strain on the browser for no reason and it will slow down your application.

React doesn't render when applied from CDN

I know how to set up a React project using npm, yeoman and it works fine.
When I follow this tutorial
http://danprince.github.io/learn-react/lessons/ex1.html and apply React from CDN, it also works - but it's an old version. If I try to apply a new version of React via CDN, I can't figure out how to render ANYTHING on the screen. For example, what's wrong with the following code?:
react:
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js'>
html:
<body>
<div id="root"> </div>
</body>
js (based on Code School tutorial exaple):
class StoryBox extends React.Component {
render() {
return( <div>Story Box</div> );
}
}
ReactDOM.render(
<StoryBox />, document.getElementById('root')
);
Since react v15.6.0 the ReactDOM module has been moved to a separate package add this to below your react <script ... /> tag:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
Snippet:
class StoryBox extends React.Component {
render() {
return( <div>Story Box</div> );
}
}
ReactDOM.render(
<StoryBox />, document.getElementById('root')
);
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<div id="root"> </div>
I think you should look at some updated react tutorials e.g.
Simple React Development in 2017

Basic react component not rendering

i'm using spring boot and my index.html is in src/main/resources/templates directory and below is the content. If i render a static content from html itself it renders but when i try to render from react component it doesn't render anything
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8"/>
<title>ReactJS + Spring Data REST</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="react"></div>
<script src="built/bundle.js"></script>
</body>
</html>
my react component is in src/main/js/ directory and app.js file
Below is the all the codes i have in the app.js file
import React from 'react';
import {render} from 'react-dom';
import RendorTest from 'components/RendorTest';
class RendorTest extends React.component{
rendor(){
return(
<div><h1>Spring Boot + Rest + React.js</h1></div>
);
}
}
var element = <RendorTest />;
ReactDOM.render(
element,document.getElementById('react')
)
I'm not sure why you're importing RendorTest and then declaring another class of the same name, but you are also extending the wrong method on the React object. You need to extend React.Component { } not .component.
You could also import React, { Component } from "react"; and then extend Component { }
As ahutch mentioned, you also need to call the render() method, rendor() is not a method of React.Component.
Kyle is right and also you want to call render() and not rendor(). This component is also probably better written as a stateless functional component, for example:
const RendorTest = (props) => {
return (
<div>
<h1>Spring Boot + Rest + React.js</h1>
</div>
)
}

dom ready event in React

I have some components like below:
Wrapper: wrap Loader and Page
Loader: some animation
Page: page content
code like this:
<body>
<div id="app"></div>
</body>
class Loader extends Component {}
class Page extends Component {}
class Wrapper extends Component {
render() {
return (
<Loader/>
<Page />
);
}
}
ReactDOM.render(<Wrapper />, document.getElementById('app'));
I want hide Loader and show Page component after DOM has compeletely loaded.
How should I write dom ready event in React?
like jQuery: $(window).on('ready')
TL;DR If I understand correctly, the answer is probably "not possible". But there is another solution...
Here's what I think you're trying to do, described as a series of steps:
page starts loading, <Loader /> component shows a "page loading" animation
page finishes loading, <Loader /> component is removed (or hidden) and <Page /> component is inserted (or shown) with the "real" page content.
Here's the problem: remember that you inject your React components into the page like this:
ReactDOM.render(<Wrapper />, document.getElementById('app'));
You can't actually inject a React component until the DOM is loaded. So by that time, either <Loader /> appears for about 2 milliseconds and disappears, or it doesn't appear at all (since the DOM is already loaded by the time it gets injected into the page).
If you're trying to show a throbber or other simple animation (like an animated GIF), I'd try a hybrid approach:
Set up your HTML like this:
<body>
<div id="app"><img src="throbber.gif" /></div>
</body>
In your script tag, include a JQuery "document ready" event handler to load the React component:
class Page extends Component {}
class Wrapper extends Component {
render() {
return (
<Page />
);
}
}
$(document).ready(function () {
ReactDOM.render(<Wrapper />, document.getElementById('app'));
});
Notice that I've left out the <Loader /> - the throbber image is doing the work of the loader.
The idea here is that while the page is loading, the throbber GIF will be throbbing away until the DOM is loaded, at which point JQuery's document ready event will fire & the contents of the div#app will be replaced.
I haven't tried this, but it should work, provided that React actually replaces the content of div#app, rather than just appending stuff to it. If that's not the case, then it's a simple matter of changing the document ready handler to something like this:
$(document).ready(function () {
$('div#app img').remove();
ReactDOM.render(<Wrapper />, document.getElementById('app'));
});
The approach I ended up using (No JQuery needed) is the following:
In the index.html, put the loader element right after the root div
<div id="root">
</div>
<div id="preloader" class="pre-loader">
<img src="..."> </img>
</div>
Then inside your index.js :
document.addEventListener("DOMContentLoaded", function(event) {
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<DashApp />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
const loadingScreen = document.getElementById("preloader");
loadingScreen.style.opacity = 0;
loadingScreen.style.display = "none";
});
So basically we simply follow a similar approach to what the other answer suggests, but without the need of JQuery cause we listen to the loading event using
document.addEventListener("DOMContentLoaded", function(event) { }
Another approach would be just placing the loader inside the root div which means React will overwrite it by default when it loads:
<div id="root">
<div id="preloader" class="pre-loader">
<img src="..."> </img>
</div>
</div>
My personal full approach can be seen in this

What does it mean when they say React is XSS protected?

I read this on the React tutorial. What does this mean?
React is safe. We are not generating HTML strings so XSS protection is the default.
How do XSS attacks work if React is safe? How is this safety achieved?
ReactJS is quite safe by design since
String variables in views are escaped automatically
With JSX you pass a function as the event handler, rather than a string that can contain malicious code
so a typical attack like this will not work
const username = "<img onerror='alert(\"Hacked!\")' src='invalid-image' />";
class UserProfilePage extends React.Component {
render() {
return (
<h1> Hello {username}!</h1>
);
}
}
ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
but ...
❗❗❗Warning❗❗❗
There are still some XSS attack vectors that you need to handle yourself in React!
1. XSS via dangerouslySetInnerHTML
When you use dangerouslySetInnerHTML you need to make sure the content doesn't contain any javascript. React can't do here anything for you.
const aboutUserText = "<img onerror='alert(\"Hacked!\");' src='invalid-image' />";
class AboutUserComponent extends React.Component {
render() {
return (
<div dangerouslySetInnerHTML={{"__html": aboutUserText}} />
);
}
}
ReactDOM.render(<AboutUserComponent />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
2. XSS via a.href attribute
Example 1: Using javascript:code
Click on "Run code snippet" -> "My Website" to see the result
const userWebsite = "javascript:alert('Hacked!');";
class UserProfilePage extends React.Component {
render() {
return (
<a href={userWebsite}>My Website</a>
)
}
}
ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Example 2: Using base64 encoded data:
Click on "Run code snippet" -> "My Website" to see the result
const userWebsite = "data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGFja2VkISIpOzwvc2NyaXB0Pg==";
class UserProfilePage extends React.Component {
render() {
const url = userWebsite.replace(/^(javascript\:)/, "");
return (
<a href={url}>My Website</a>
)
}
}
ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
3. XSS via attacker controlled props
const customPropsControledByAttacker = {
dangerouslySetInnerHTML: {
"__html": "<img onerror='alert(\"Hacked!\");' src='invalid-image' />"
}
};
class Divider extends React.Component {
render() {
return (
<div {...customPropsControledByAttacker} />
);
}
}
ReactDOM.render(<Divider />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Here are more resources
Exploiting Script Injection Flaws in ReactJS Apps
The Most Common XSS Vulnerability in React.js Applications
How Much XSS Vulnerability Protection is React Responsible For?
https://github.com/facebook/react/issues/3473#issuecomment-90594748
https://github.com/facebook/react/issues/3473#issuecomment-91349525
Avoiding XSS in React is Still Hard
Avoiding XSS via Markdown in React
React automatically escapes variables for you... It prevents XSS injection via string HTML with malicious Javascript.. Naturally, inputs are sanitized along with this.
For instance let's say you have this string
var htmlString = '<img src="javascript:alert('XSS!')" />';
if you try to render this string in react
render() {
return (
<div>{htmlString}</div>
);
}
you will literally see on the page the whole string including the <span> element tag. aka in the browser you will see <img src="javascript:alert('XSS!')" />
if you view the source html you would see
<span>"<img src="javascript:alert('XSS!')" />"</span>
Here is some more detail on what an XSS attack is
React basically makes it so you can't insert markup unless you create the elements yourself in the render function... that being said they do have a function that allows such rendering its called dangerouslySetInnerHTML... here is some more detail about it
Edit:
Few things to note, there are ways to get around what React escapes. One more common way is when users define props to your component. Dont extend any data from user input as props!

Resources