React without JSX
14 August, 2019
Time to read: 1 mins
Table of contents
Each JSX element is just syntactic sugar for calling React.createElement(component, props, …children).
I removed the JSX from the boilerplate of the CRA app, and I replaced it with createElement
calls for practice. Yes, but why?—you may ask. Here are some advantages of using createElement
over JSX:
- No build process is required for transpiling JSX.
- See React from a different perspective.
And here are some disadvantages:
- Hard to read.
- Arguably harder to write.
Some useful resources:
The code
src/index.js
src/index.js
import { createElement as e } from "react";
import { render } from "react-dom";
import App from "./App";
import "./index.css";
render(e(App), document.getElementById("root"));
src/App.js
src/App.js
import { createElement as e } from "react";
import Button from "./components/Button";
import logo from "./logo.svg";
import "./App.css";
function App() {
return e(
"div",
{ className: "App" },
e(
"header",
{ className: "App-header" },
e("img", { className: "App-logo", src: logo, alt: "logo" }),
e(
"p",
null,
"Edit ",
e("code", null, "src/App.js"),
" and save to reload."
),
e(
"a",
{
className: "App-link",
href: "https://reactjs.org",
target: "_blank",
rel: "noopener noreferrer",
},
"Learn React"
),
e(
Button,
{
style: {
backgroundColor: "rebeccapurple",
marginTop: "32px",
fontSize: "20px",
},
className: "my-button",
onClick: (e) => console.log(e.target),
// children: [
// e("strong", { key: null }, "Click "),
// "me ",
// e("i", { key: null }, "NOW!")
// ]
},
e("strong", null, "Click "),
"me ",
e("i", null, "NOW!")
)
)
);
}
export default App;
And this is a React app without a build process (bad idea). You still need some babel helpers though if you want to create reusable components.
index.html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Hello World</title>
<link
rel="stylesheet"
href="https://unpkg.com/normalize.css@7.0.0/normalize.css"
/>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 20px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: Georgia, "Times New Roman", Times, serif;
}
</style>
</head>
<body>
<div id="root"></div>
<script
crossorigin
src="https://unpkg.com/react@16/umd/react.production.min.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"
></script>
<script src="/babel-helpers/object-spread.js"></script>
<script src="/babel-helpers/object-without-properties.js"></script>
<script>
var e = React.createElement;
function Button(props) {
var style = props.style;
var restProps = _objectWithoutProperties(props, ["style"]);
return e(
"button",
_objectSpread(
{},
{
style: _objectSpread(
{},
{
padding: ".5em 1em",
cursor: "pointer",
border: 0,
borderRadius: "2px",
backgroundColor: "rebeccapurple",
color: "white",
},
style
),
},
restProps
)
);
}
var App = function () {
return e(
"div",
{
style: {
minHeight: "100vh",
backgroundColor: "#1d1d1d",
color: "white",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
},
},
e(
"div",
{ style: { padding: "16px" } },
e(
"h1",
{ style: { fontSize: "3em", textAlign: "center" } },
"Hello World!"
),
e(
"p",
{ style: { maxWidth: "400px", marginBottom: "40px" } },
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque minima temporibus tenetur natus aspernatur dolore eius adipisci quo neque perspiciatis!"
),
e(
Button,
{
onClick: function (e) {
console.log(e.target);
},
style: {
backgroundColor: "#de2b61",
float: "left",
},
},
"Click me"
)
)
);
};
ReactDOM.render(e(App), document.getElementById("root"));
</script>
</body>
</html>
Here I use the objectSpread
to combine the Button
props into one object as well as its style
prop into a different one. I’m also using the objectWithoutProperties
to extract the style from the rest of the props.
Other things to read
Popular
- Reveal animations on scroll with react-spring
- Gatsby background image example
- Extremely fast loading with Gatsby and self-hosted fonts