what is the purpose of using demo or root - reactjs

ReactDOM.render(
<App />,
document.getElementById('root')
So what should I understand when i see something like this at the end of the app? What does 'root' or 'demo' stand for?

It's the element that exists in the original HTML that all of the React contents go into. For example, if your HTML contains:
<body>
<div>Maybe some other content here</div>
<div id="root"></div>
</body>
React rendering into the #root means that everything App renders will be put into that element:
<div id="root">
<!-- App populates this element -->
</div>
The element selected to be populated can be any element you want - it doesn't have to be root or demo in particular.

I'm assuming you're using Create React App. Have a look at public/index.html. There you'll see <div id="root"></div> which is what document.getElementById('root') is referring to.

Inside the HTML main file index.html of a React App, normally, you might see a <div> tag with id=root.
This code:
ReactDOM.render(
<App />,
document.getElementById('root')
MEANS: Render the whole React App into the element with id=root.

Many React beginners are curious about this thing, so was I. Therefore I will try explaining this in simple words.
When Browser gets response from server and starts rendering, it goes to the root file which in most cases is public/index.html, and render the same file most first.
Inside this html a <div> element is written whose id is "root"
<div id="root"> <div>
Then control goes to another file that is index.js.
Inside this .js file, a component is used (in most React apps this component is called <App/>.
ReactDOM.render(
<App />
document.getElementById("root"),
);
This <App/> component is the most first component that is rendered on the screen. Every Component is defined inside this component or it's children.
And document.getElementById("root") renders the index.html file that is the root file.
This is how all the components are rendered and your React App starts working.

Related

How to add React to html using modern features

I have been tasked to add a react component to a website that is currently a html page and an empty main.js file.
How would I go about creating a react component within my script that allows use of modern feature etc like useState and useEffect?
On the official docs there is a 2 year old article which relies on components rather than hooks.
Once you add React and ReactDOM to your HTML page:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
you can simply render a React component to the existing HTML page like:
ReactDOM.render(
<MyComponent test={true} />,
document.getElementById('container')
);
where container is the id of element your React component should be rendered within.

React is not rendering both modules to the DOM

I'm trying to render two modules to the DOM.
When I do an 'npm start', it runs, but it's only showing the CharacterApp part. The main app(App) doesn't show up.
Here is my index.js file code:
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import CharacterApp from "./Characters/App";
import './CharacterApp/index.css';
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<CharacterApp />, document.getElementById("root"));
CharacterApp is structured like this:
function App() {
....
}
export default App
And App looks like this:
const App = () => (
....
);
export default App;
Since it's not showing errors, I'm kinda lost as to why it's not showing both on the DOM.
Is there anything I'm missing?
Thanks!
React will replace the entire content of the specified element with the render output when it is called - which is also why you should not render into document.body.
You will want to use two separate containers (perhaps create another div element and give it a unique id). Alternatively, if you don't need to have the separation of two react apps, you could instead combine the two into a single app:
ReactDOM.render(
<React.Fragment>
<App />
<CharacterApp />
</React.Fragment>,
document.getElementById('root')
)
How can it render two modules ? you are rendering the App module in a div with id='root' and then you are overwriting it with another module. Its the correct behaviour you can not render two modules like that.
If you want to render both modules in the same page, create a separate component and import your App and CharacterApp in that module and then render that new component in the dom i.e
ReactDOM.render( <YourNewComponent /> ,
document.getElementById('root')
)
And if you do not want to create a seperate component, you can just simple do this.
ReactDOM.render(
<React.Fragment>
<App />
<CharacterApp />
</React.Fragment>,
document.getElementById('root')
)
`ReactDOM.render(
<React.Fragment>
<App />
<CharacterApp />
</React.Fragment>, document.getElementById('root'))`
> this will work. you can not use same 'root' for rendering 2
> components. instead you can group them in one or use different div
> Ids.
This code is the culprit:
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(<CharacterApp />, document.getElementById("root"));
You're using the same div for showing your apps, so the second statement is replacing the App component with CharacterApp.
You can create two divs in index.html, say, div#root-app and div#root-character-app, and then render the two components to the two containers respectively.

How to embed React Components in html pages

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

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

Static website using React

I am making a static website and using Gulp to process all the files.
Static HTML
Firstly I had a bunch of static HTML files each with the content for the page. Example index.html:
<p>Home</p>
Then I had a layout.html file with HTML that is the same for each page. It looked like this:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="assets/styles.min.css">
</head>
<body>
<div id="contents">
<%= contents %>
</div>
<script src="assets/scripts.min.js"></script>
</body>
</html>
Then, in the gulpfile, I would process the pages using the gulp-wrap plugin like this:
gulp.task("html", () => {
return gulp.src(["html/**/*.html", "!html/layout.html"])
.pipe(wrap({ src: project.layout }))
.pipe(gulp.dest(project.build));
});
And this, as expected, created all the HTML files as required.
Using React
Now I want to use React. So in my main script that gets included into every page I wrote this:
import React from "react";
import { render } from "react-dom";
render((
<p>This would be some Page component...</p>
), document.body);
This, of course, replaces the body content of every page, so I turned to the react-router:
import React from "react";
import { render } from "react-dom";
import { Router, Route, browserHistory } from "react-router";
render((
<Router history={ browserHistory }>
</Router>
), document.body);
I guess this would work (after putting some routes into the router, of course), but what are the HTML files for?
Questions
How do I use the HTML files? Will I just leave them empty so that Gulp generates the same HTML file layout.html everywhere it's needed? (Or something equal to copy the file...) I need some files there so that routes like site.me/about work. This would leave everything up to the router.
Do I render a page-specific component in every page HTML file? This means having something like this in the index.html file:
<script>render(<Index />, document.body);</script>
Some other react-router wizardry?
How would you do this?
What I've done in this case is to have just one single HTML file that has the application in it. I then set this file up on the server to always be loaded irrespective of what the actual request path is.
Once that's done, reading the path on React Router and showing the correct components happens as usual. The key is that all routes load the same HTML page and the routing (deciding which component to show where and which props to load into it) happens inside React Router.

Resources