How to add React to html using modern features - reactjs

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.

Related

Add React app build to my existing website div

Is it possible to add a build index.html of a React app to a div in my HTML/ColdFusion website?
I built a chatbot in React using hooks.
Bellow is my App.js which imports my ChatBot.js component.
import './App.css';
import MyChatBot from './ChatBot';
function App() {
return (
<div className="App">
<MyChatBot/>
</div>
);
}
export default App;
It is working. I have a ColdFusion/HTML website where I would like to include this "chatbot" or the generated index.html from npm run build to a div
<!-- ColdFusion Website here --->
<div id="myChatBot"></div>
The idea is to have the React application inside that div. Is it possible?
Thank you.
Yes, you can. You just need to pass the element ( where you want to mount the react app ) to ReactDOM.render method. Then bundle your react app using a bundler, say webpack, and include that bundle via script tag or via the current build process in your app's html.
HTML
<!-- Website Markup --->
<div id="myChatBot"></div>
<!-- Include React bundle --->
<script src="bundle.js"></script>
React
import ReactDOM from "react"
import App from "./App"
ReactDOM.render(<App/>, document.getElementById("myChatBot"))
Hope this is helpful to you: https://reactjs.org/docs/add-react-to-a-website.html
Gist of it is you have import the React scripts and render it to that id:
const domContainer = document.getElementById('myChatBot');
ReactDOM.render(e(LikeButton), domContainer);

How to use function instead of class in Nextjs custom document for Styled Components?

I'm using NextJS and Styled Components. Reading the documentation below I added a custom _document.js in NextJS to make Styled Components works.
Styled Components Doc
The example code is written in a React Class, is there a way of converting this to a function?
This is possible since Next 11.1.1, thanks to #28515, but the feature seems currently undocumented.
See an example below:
import { Html, Head, Main, NextScript } from 'next/document'
const Document = () => (
<Html>
<Head/>
<body>
<Main />
<NextScript />
</body>
</Html>
)
export default Document
The answer is that there is no good way to do it, I guess you could somehow override it but Next.js uses _document and _app for in its custom runtime and it is not a good idea to override it.
_document's purpose:
A custom Document is commonly used to augment your application's <html> and <body> tags.
Also, note that using any logic (apart from this inside getInitialProps) inside _document is unadvisable: https://nextjs.org/docs/advanced-features/custom-document#caveats

what is the purpose of using demo or root

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.

ReactJS ReactDOM Render for Separate Pages

I am in the process of migrating my pages from html and jquery to using React and I am aware that React Router and Redux are methods to handle routing when building a react application, but for the time being, I was wondering how I can change my setup to be able to render different react components for different pages. At the moment, I am able to render one react component when my index page is loaded, but I thought I could add another ReactDOM.render() beneath it and target a different div id for the component on a different page, but I noticed an error, Invariant Violation: Target container is not a DOM element. Is this related to not using a react router or something else?
here is my index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import ActivityFeed from './components/App/ActivityFeed/ActivityFeed';
import CreateAnnotation from './components/App/Annotation/CreateAnnotation';
ReactDOM.render(<ActivityFeed />, document.getElementById('annotation-card'));
ReactDOM.render(<CreateAnnotation />, document.getElementById('annotation-form'));
Here is <CreateAnnotation/>:
import React from 'react';
//GET /api/activity-feed and set to state
export default class CreateAnnotation extends React.Component {
constructor(props, context) {
super(props, context);
this.state = this.context.data || window.__INITIAL_STATE__ || {
notifications: [],
reportLinks: [],
files: []
}
}
render() {
return (
<div>
<p>test</p>
</div>
)
}
}
Here is the view file:
<!DOCTYPE html>
<head>
{{> app/app-head}}
</head>
<body>
<div id="annotation-form"></div>
{{> general/bundle-js}}
</body>
</html>
{{> general/bundle-js}}:
<script src="/bundle.js"></script>
ReactDOM renders a React element into the DOM in the supplied container
and return a reference to the component (or returns null for stateless
components). If the React element was previously rendered into
container , this will perform an update on it and only mutate the DOM
as necessary to reflect the latest React element.
Technically speaking you cant render more than one React element into the DOM with multiple ReactDOM render function as it would always replace the previous rendered DOM.
See https://reactjs.org/docs/react-dom.html
The right way to do is to create multiple components and import them into App.js file. Then, your index.js file is supposed to import App.js file
as one whole component, with ReactDOM only renders App.js as a single component.

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