Replace React createElement Function Call with JSX

Kent C. Dodds
InstructorKent C. Dodds

Share this video with your friends

Send Tweet
Published 5 years ago
Updated 2 years ago

In this lesson, we'll learn what JSX is and how it can replace calls to React's createElement API. We will go over how you can interop regular Javascript right in the JSX with curly brackets. We will learn how to pass props to JSX and how to override and props that get passed in. In addition to the noted className difference, there are a number of other differences with attributes in JSX than those in HTML.

[00:00] Writing our entire app using React.create element is totally possible, but it's not entirely ergonomic. The React team created JSX to allow us to write our UI in a way that's a little bit more familiar to us. This is JSX, and it looks similar to HTML and behaves in similar ways. We're going to convert this to use JSX.

[00:22] Let's go ahead and do that. I'm going to just comment this out and we'll say const element equals div. We want the class name to be container, and then the children to be hello world. Then we'll close off that div. We'll save that. When we refresh, we're going to get a syntax error.

[00:42] This is actually not JavaScript syntax at all. This JSX, so it needs to be transpiled into this React create element call. We can use Babel to do this. Normally, to do this you would have a build system set in place with web pack or something like that, but we're just going to use Babel standalone so that we can do this right in the browser without having any sort of build system.

[01:06] I'll go ahead and paste this script tag there. That brings in Babel standalone. Then I'm going to change this from text JavaScript to text Babel to make that work. Now I refresh, and I get hello world. Perfect.

[01:21] It all looks exactly the same. The HTML output is exactly the same as we had before with the class container. Now, with this new syntax, we can do a couple of tricks, and it looks a little bit nicer. It's easier to compose these things together.

[01:36] Let's learn a couple of things about JSX. There are a couple of things that are different. For example, in HTML, you use class, and in JSX, you use class name. Then we provide our attributes just like we would in HTML with a string here. Then our children, and we can provide any number of children, and it doesn't have to be all on one line.

[01:57] Let's say we wanted to take this hello world and externalize it to variable. How do we do that? Let's go ahead and copy this. We'll make const content equals string hello world. Then we'll replace this hello world with an interpolation. We'll put content in here.

[02:15] This interpolation is denoted by these curly braces. When you do this, you're exiting JSX land and entering JavaScript land. You can do any JavaScript that you want to as long as it evaluates to an expression. I'll save that, refresh. We'll see that we get exactly what we had before.

[02:32] Now, inside of these curly braces can literally be anything. I'm going to make an immediately invoked arrow function. We'll refresh and we get exactly the same thing. That's one of the really nice things about JSX is that once you put in these curly braces, you are in JavaScript land and you can do anything that you want to inside of this JSX.

[02:55] That also counts for the class name prop or any props that you're passing to these components. Here I'm going to use curly braces instead of that quote. We'll say that my class name equals container. Then inside of these curly braces, I can do any JavaScript that I want. I'll do my class name. I refresh, and here we have the classes container.

[03:22] This allows me to do any kind of interpolation. Hi there, we have container hi there. That gives me a lot of power and flexibility to have my view logic as part of my markup.

[03:37] One other thing that is pretty common to do with JSX is we're going to create a props object here. We're going to say that class name prop we want to be container, and the children prop will be hello world. Then we're going to take this div and remove all the props and make it a self-closing React element.

[04:00] Then we'll do this open curly braces, so we'll enter JavaScript land. We'll do ...props. This is similar to object spread in JavaScript. We are spreading these props, const name and children, across this div here. If I save this and refresh here, we're going to get the exact same thing. We have the const container and hello world.

[04:23] Now, let's say that this object is coming to us from some other place. We're going to want to override it or have the props override some of our things. We'd say, "If they don't give me a class name, then I want it to be my class." We refresh here.

[04:41] They do give us a class name, so the class name's still going to be container. Let's say that we want to override whatever class name they pass in. They can pass us a class name, but we're going to use our own class name. What we're going to do is we'll take the class name prop and we'll move it over on the other side of this props spread here. We'll see class is my class now.

[05:01] The same kind of thing happens with the children prop. We could pass a children prop and have it be whatever we want there, and it would override whatever's in the props there. Or we can use the regular children here either, and that will also override whatever is in props.

[05:20] Those are a couple of the tricks that you can do with JSX. The basic idea is you enter JSX land with the caret. You specify the element that you want to have rendered, and then you specify any props just like you would attributes on HTML.

[05:33] There are some differences here like I noted with class name, and there are some others as well. Then you can pass your children, and then you close your JSX element. In addition, you can do a self-closing tag here as well if you don't want to put any inside of the JSX element.

ahairshi
ahairshi
~ 5 years ago

I have a very basic question. I need to know whether we need to create an element every time before calling render method. How to replace the World with Universe?

var greetings = 'World'
var element = <h1>Hello, {greetings}</h1>

ReactDOM.render(
  element,
  document.getElementById('root')
);

greetings = 'Universe'

ReactDOM.render(
  element,
  document.getElementById('root')
);
Kent C. Dodds
Kent C. Doddsinstructor
~ 5 years ago

Hi ahairshi 👋

Thanks for the question. This is fairly fundamental JavaScript and has to do with the fact that a variable reassignment does not change the result of where the variable was used in the past. Alternatively you could make this work by making the variable an object and manipulating that object:

var state = {}
state.greetings = 'World'
var element = <h1>Hello, {state.greetings}</h1>

ReactDOM.render(
  element,
  document.getElementById('root')
);

state.greetings = 'Universe'

ReactDOM.render(
  element,
  document.getElementById('root')
);

So that will work as you expect it to because you're manipulating the object that the element is referencing.

This is not idiomatic react however. If you want to learn more about managing state in react, keep watching :) Good luck!

Jared Hensley
Jared Hensley
~ 4 years ago

Very solid Kent, would love to see you do more React fundamentals! Do you have any other recommended resources?

RentPath User 5
RentPath User 5
~ 4 years ago

thanks Kent for a solid course;

can you explain this bit of code: (() => content)(), especially the last set of parenthesis?

Thanks

Kent C. Dodds
Kent C. Doddsinstructor
~ 4 years ago

Hi Jared Hensley, you might appreciate this blog post: How to React.

Hi RentPath User 5 :) So, let's refactor that code and maybe it'll make more sense:

const getContent = () => content
getContent()

So the original code is called an immediately invoked function expression (IIFE for short). It's a way that you can encapsulate some logic within a closure (function) without having to give the function a name. In the video I just used it to demonstrate that any JavaScript expression can be used in the { and } of JSX. I wouldn't normally recommend doing something like that, but it could be useful if you want to define variables and keep them scoped to the function. In the future there may be a better way to do that with do expressions.

Good luck!

Zac Dobbs
Zac Dobbs
~ 3 years ago

This is so cool

Conekta
Conekta
~ 3 years ago

Why isn't my code showing anything on Code Sandbox? It's exactly the same a in the video.

<div id="root"></div>
<script src="https://unpkg.com/react@16.3.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.3.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

<script type="text/babel">
  const rootElement = document.getElementById("root");

  const content = "Hello World";
  const element = <div className="container">{content}</div>;
  ReactDOM.render(element, rootElement);
</script>
Stacie
Stacie
~ 3 years ago

Why isn't my code showing anything on Code Sandbox? It's exactly the same a in the video.

<div id="root"></div>
<script src="https://unpkg.com/react@16.3.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.3.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

<script type="text/babel">
  const rootElement = document.getElementById("root");

  const content = "Hello World";
  const element = <div className="container">{content}</div>;
  ReactDOM.render(element, rootElement);
</script>

I don't think that the Code Sandbox can handle Babel.