Pure React

When I first started learning JavaScript (which was only a couple years ago), React was already a pretty big thing. And so I joined the club and started coding in React. And like a lot of people I used create-react-app (CRA) to quickly get up and running with my projects. It removes the necessity to spend time setting up your build tools, everything "just works". What we will go over in this post is how you can write pure react without the build tools that CRA uses behind the scenes.

Transpiler Magic

One of the tools that CRA sets up for you is Babel. It makes sure the browser can understand the app by turning your JSX into plain JavaScript. What this means is that to write modern react using JSX we need tools like this. On a side note, if you are using Typescript with react check out how we exchanged Babel&TSC for SWC and improved our build time! But let's look into how we can still use the react library and write our components in good old JavaScript without the build tools. Then we can see how useful they are and appreciate them instead of getting frustrated when it "just doesn't work".

Here is a common way of writing react components today:

const HelloWorld = () => {
  return <h1 className="greeting">Hello, world!</h1>
};
ReactDom.render(<HelloWorld />, document.getElementById("root"));

And here is the exact same thing without JSX:

const HelloWorld = () => {
  return React.createElement("h1", { className: "greeting" }, "Hello World!");
};
ReactDOM.render(React.createElement(HelloWorld), document.getElementById("root"));

The second example is what Babel does to the first example, it compiles the JSX down to a bunch of React.createElement calls.

The React.createElement function

Let's take a look at what the React.createElement function is.

It takes three parameters:

  • type can be an html tag or another react component
  • props are attributes for the element (this can also be null or {})
  • children contain other html tags or react components

Let's think of components as stamps. What we have done so far is create the HelloWorld stamp, and stamped it once using ReactDOM.render. That is what the React.createElement function does, it generates markup. It creates an instance of a component, and since we passed h1, that tag is output to the DOM. Had we put something made-up, my-own-tag the output would look like this.

<div className="root">
	<my-own-tag>Hello World</my-own-tag>
</div>

Here is a simplified example of the object that the React.createElement function call creates.

const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

We call these objects "react elements" and they are read by react and used to keep the DOM up to date. If you log the function call you can check out the full object.

If you want an element with multiple children, just pass it an array of elements.

const Greetings = () => {
  return React.createElement("div", { className: "greetings" }, [
		React.createElement("h2", {}, "Hello World!"),
    React.createElement("h2", {}, "Goodbye World!"),
	]);
};

Now it doesn't take many components before this gets tiresome, but now you can at least appreciate writing JSX, and let the tools figure out the rest.

Do you have any more questions about working in Telia? Let us know and we’ll be happy to chat about it. Drop us a line on twitter!


Frontend, React, JSX, development