Sample ReactJS from reactjs.org code not working with JSX - javascript

I am trying to follow the code sample given in this link: https://reactjs.org/docs/add-react-to-a-website.html#add-react-in-one-minute to run a react component into an existing HTML page.
but when I am trying to replace the native JavaScript with JSX I am getting this error:
ReferenceError: e is not defined
I know I need to replace the e(LikeButton)) with something. but it's not mentioned there what to update in render code.
likebutton.js:
'use strict';
// const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
if (this.state.liked) {
return 'You liked this.';
}
// Display a "Like" <button>
return (
<button onClick={() => this.setState({ liked: true })}>
Like
</button>
);
}
}
index.html:
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<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#6/babel.min.js"></script>
<!-- Load our React component. -->
<script src="{{ asset('theme_assets/js/react/likebutton.js') }}" type="text/babel"></script>
<script>
const domContainer = document.querySelector('#like_button_container');
ReactDOM.render(e(LikeButton), domContainer);
</script>

Replace
ReactDOM.render(e(LikeButton), domContainer);
With
ReactDOM.render(<LikeButton />, domContainer);
Working Code here
https://jsbin.com/wuqoluyovu/edit?html,console,output

Related

How can I convert class component into functional component when adding React library to a Website?

I want to use react component in html file. It is for micro frontend. So I follow this react official doc for Add React to a Website.
The sample code is as below:
index.html
<html>
<body>
<p>
This is the first like.
<div class="like_button_container" data-commentid="1"></div>
</p>
<p>
This is the second like.
<div class="like_button_container" data-commentid="2"></div>
</p>
<p>
This is the third like.
<div class="like_button_container" data-commentid="text"></div>
</p>
<script src="https://unpkg.com/react#17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js" crossorigin></script>
<script src="like_button.js"></script>
</body>
</html>
like_button.js
"use strict";
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
return e(
"button",
{
onClick: () =>
this.setState((prevState) => ({
liked: !prevState.liked,
})),
},
this.state.liked ? "Liked " + this.props.commentID : "Unliked"
);
}
}
document.querySelectorAll(".like_button_container").forEach((domContainer) => {
const commentID = domContainer.dataset.commentid;
ReactDOM.render(e(LikeButton, { commentID: commentID }), domContainer);
});
Above code is working fine but I want to convert like_button.js, which is class component into functional component.
Thanks in advance.
You need to use babel standalone script to transcompile the code, and you need to include the script for react and react-dom, use these will work.
<html>
<head>
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/#babel/standalone#7.15.7/babel.min.js"></script>
</head>
<body>
<div id="react-container"></div>
<script type="text/babel">
const App = () => <div>Hello!</div>
ReactDOM.render(
<App />, document.getElementById('react-container'))
</script>
</body>
</html>
Babel Standalone converts ECMAScript 2015+ into the compatible version of JavaScript for your browser, CDN usage is described in official documentation, check babel standalone section: Babel Standalone

react-json-schema tutorial does not show up in browser

I am completely new to web development (html/js) but would now like to use the react-json-schema package which works great in the provided sandbox.
However, I can't even get the tutorial to work. I have written an html, as given in the tutorial:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<script type="text/jsx" src="react.js"></script>
</body>
</html>
the corresponding javascript file "react.js":
const Form = JSONSchemaForm.default;
const schema = {
title: "Test form",
type: "string"
};
ReactDOM.render((
<Form schema={schema} />
), document.getElementById("app"));
However, the schema simply does not show up in a browser when opening the html. There is no error message.
Things I have tried:
1.) importing the scripts from the cdn, so adding these lines in the html head:
<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/#rjsf/core/dist/react-jsonschema-form.js"></script>
2.) re-installing npm and the react-json-schema, react and react-dom packages both locally and globally
3.) importing said packages in the js:
import react from React
import import ReactDOM from 'react-dom'
import Form from "#rjsf/core";
try below:
import Form from 'react-jsonschema-form';
class Index extends DataComponent{
constructor(props){
super(props);
this.state={
schema: {
type: 'object',
title: 'Info',
properties: {
task: {
type: 'string',
title: 'First Name'
}
}
}
}
}
render(){
return(
<Form
schema={this.state.schema}
/>
)
}
}
If you have installed the library then remove
//const Form = JSONSchemaForm.default;

How to create and render a React Component after babelify/transpiling?

I have a hello world react component that is written in JSX, transpiled with babel, and then included in the hello.html template of a Flask app. What I have working is creating and rendering the component before transpiling as such:
const hello = <Hello name="world" />;
ReactDOM.render(hello, document.getElementById('hello'));
How can I do those two steps in a <script> tag in my hello.html template? My goal is to be able to pass that name variable from the template to the component and then render it.
A little more context:
The JSX hello.js looks like this:
import React from 'react';
import ReactDOM from 'react-dom'
import { render } from 'react-dom'
class Hello extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div>Hello {this.props.name}!!!</div>
)
}
}
//The following works:
//const hello = <Hello name="world" />;
//ReactDOM.render(hello, document.getElementById('hello'));
hello.html looks like this:
<html>
<head>
</head>
<body>
<div>ASDF</div>
<div id="hello"></div>
</body>
{# The following line is a post babelify (transpiled) hello.js #}
<script type="text/javascript" src="{{ url_for('static', filename='js/hello.js') }}"></script>
<script type="text/javascript">
{#
What goes here? The code in the above section does not work.
The transpiled code defines a "var Hello = /*#__PURE__*/ function (_React$Component) { ...".
const hello = Hello(); does not throw an error, but also does not render or pass an argument.
hello.render(); is also something that I have tried, along with arguments for div/id to render in and name.
#}
</script>
</html>
Correction: Calling Hello() does not throw an error if the script is text/babel, in which case the script probably isn't doing anything.
The Flask route looks like this:
#app.route(u'/')
def index():
return render_template(u'hello.html', name="universe")
Two ways you can pass variables from your server application to react component:
Use the html data-variable prop.
Create a global variable. Something like window.variable
Then you should be able to access variable as a props like props.variable in your react-component.
My recommended approach I would take is to use a bundler such as SystemJS (version 2), and you will have something like the following:
<!DOCTYPE html>
<html>
<head>
<script src="node_modules/core-js-bundle/minified.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script type="systemjs-importmap" src="systemjs.imports.json"></script>
<script src="node_modules/systemjs/dist/system.min.js"></script>
<script src="node_modules/systemjs/dist/extras/named-exports.min.js"></script>
<script>
System.import('../.playground/index.js').catch(function (err) { console.error(err); });
</script>
</head>
<body>
<div>ASDF</div>
<div id="hello"></div>
</body>
</html>
And index.js will look something like this
ReactDOM.render(
(< Hello/>),
document.getElementById('app')
);
Then your systemjs-importmap will look like this
{
"imports": {
"react": "../node_modules/react/umd/react.production.min.js",
"react-dom": "../node_modules/react-dom/umd/react-dom.production.min.js",
// ... other named exports you want to add like the Hello component here
}
}

How to make script type both text/babel and module?

It works perfectly because I haven't included JSX, but when I replace the script type with text/babel, it doesn't work because the module fails to load. browser.js the Babel compiler.
Here... JSX works only when i replace script type with text/babel but the problem is module fails to load since the script is not module. Any idea how make it work with JSX?
<div id="root">
</div>
<script type="module">
import './react.min.js';
import './react-dom.min.js';
import './browser.js';
class Hello extends React.Component {
render() {
return React.createElement('div', null, `Hello ${this.props.toWhat}`);
}
}
ReactDOM.render(
React.createElement(Hello, {toWhat: 'World'}, null),
document.getElementById('root')
);
</script>
UPDATE July 2021
As per mh sattarian's answer you now don't need data-plugins="transform-es2015-modules-umd" to use native es6 module's import/export etc. Instead you simply add data-type="module"
Original Answer
Just in case if some one comes here looking for answer
There is a support for data-plugins and data-presets in babel standalone
<script data-plugins="transform-es2015-modules-umd" type="text/babel">
see more here
Babel standalone
As mentioned in the docs, it's added in: v7.10.0.
If you want to use your browser's native support for ES Modules, you'd
normally need to set a type="module" attribute on your script tag.
With #babel/standalone, set a data-type="module" attribute instead,
like this:
<script type="text/babel" data-type="module">
I think the question was if it is possible to use a script tag with two or more types at the same time (e.g. something like type="module, txt/babel"). As far as I know the answer is NO.
JonDotsoy's answer helps with reduce typing React.createElement over and over again but even with such a "variable shortcut" it's not as comfortable as JSX when using larger templates with nested elements because h('div', {}, 'hello!!')... is difficult to maintain in such cases.
The only way I found to combine native browser module support and in-browser Babel for JSX without using any build tool is this ... a rather dirty hack that uses eval and should not be used for production apps:
index.html
<body>
<div id="app"></div>
<!-- Scripts ------- -->
<script src="vendor/js/babel.min.js"></script>
<script src="vendor/js/react.development.js"></script>
<script src="vendor/js/react-dom.development.js"></script>
<script src="app/app.js" type="module"></script>
</body>
app/app.js
import ComponentOne from "./ComponentOne.js";
let template = `
<div>
<h1>Heading</h1>
<hr />
<ComponentOne msg="MsgText-ComponentOne" />
</div>
`;
const App = () => {
return (
eval(Babel.transform(template, { presets: ['es2017', 'react'] }).code)
);
};
ReactDOM.render(
React.createElement(App, null),
document.getElementById("app")
);
app/ComponentOne.js
import ComponentTwo from "./ComponentTwo.js";
let template = `
<div>
<h2>This is ComponentOne</h2>
<p key="2">Property "msg" content: {props.msg}</p>
<ComponentTwo msg="MsgText-ComponentTwo" />
</div>
`;
const ComponentOne = (props) => {
return(
eval(Babel.transform(template, { presets: ['es2017', 'react'] }).code)
);
};
export default ComponentOne;
app/ComponentTwo.js
let template = `
<div>
<h2>This is ComponentTwo</h2>
<p key="2">Property "msg" content: {props.msg}</p>
</div>
`;
const ComponentTwo = (props) => {
return(
eval(Babel.transform(template, { presets: ['es2017', 'react'] }).code)
);
};
export default ComponentTwo;
you may prefer to use an alias to createElement. This way is faster for the engine.
For example use h or e.
const { createElement: h } = React;
const App = () => {
return h('div', {}, 'hello!!');
}
Otherwise, it is possible to use #babel/standalone module, please see more on here https://babeljs.io/docs/en/next/babel-standalone.html.
<div id="app"></div>
<!-- Load Babel -->
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<!-- Your custom script here -->
<script type="text/babel">
const { render } = ReactDOM;
const App = () => {
return <div>hello!!</div>
}
render(<App />, document.getElementById('app'));
</script>

How to pass props stated in HTML to root component

I'm using a simple component in React for two buttons in an existing HTML/JavaScript, (not a React project) project. It looks like this:
//Submitcancel.jsx
'use strict'
class Submitcancel extends React.Component {
constructor(props) {
super(props)
console.log(props)
}
render() {
return (
<div className="form-buttons">
<div className="ibm-col-12-12">
<button id="buttonSubmit" name="buttonSubmit" value="Submit" type="submit" className="ibm-btn-pri dw-btn-blue">Submit</button>
<button value="Cancel" id="buttonCancel" name="buttonCancel" className="ibm-btn-sec dw-btn-blue">Cancel</button>
</div>
</div>
)
}
}
ReactDOM.render(
// React.createElement(Submitcancel),
// document.querySelector('#react-submit-cancel')
)
The HTML file looks like this:
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<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>
<!-- Load React component. -->
<script type="text/babel" src="./js/components/Submitcancel.jsx"></script>
The component element where I would like to define the props is like this:
<div id="react-submit-cancel"></div>
If you want to grab the button texts from your HTML <div>, you need a non-react solution for that:
<div id="react-submit-cancel" submitText="Go"></div>
then in your initialization:
const el = document.querySelector('#react-submit-cancel');
const props = {
submitText: el.getAttribute("submitText") || "Submit", // default value
cancelText: el.getAttribute("cancelText") || "Cancel"
};
ReactDOM.render(React.createElement(Submitcancel, props), el)
For a pure React solution you'd have to wrap the Submitcancel component so you can pass props to it using JSX.
When you need to pass data through props, you just need to mention props id and value along with component.
In your case code will be like:
ReactDOM.render(
<Submitcancel FirstName={"first name"} LastName={"last name"}/>,
document.getElementById("react-submit-cancel")
)
Above example FirstName and LastName are two props
You can get the value in constructor inside the Submitcancel component.
constructor(props) {
super(props)
console.log(props.FirstName)
console.log(props.LastName)
}
Please follow this code:
ReactDOM.render(
<Submitcancel />,
document.getElementById("react-submit-cancel")
)

Categories