FREELessons: 2Length: 15 minutes

Next lesson playing in 5 seconds

  • Overview
  • Transcript

1.2 Thinking in React: JSX Deep Dive

In this lesson, we’ll dive into JSX, React’s template language. I’ll show you how JSX is a natural syntactic expansion of JavaScript, and together we’ll discover the ins and outs of using JSX with native HTML elements and custom React components. Along the way, we’ll compare each bit of JSX with the JavaScript into which it compiles so that we get a sense of what’s happening under the hood.

Related Links

1.Thinking in React: JSX Deep Dive
2 lessons, 15:21


Thinking in React: JSX Deep Dive

1.2 Thinking in React: JSX Deep Dive

[MUSIC] Hi guys. This is Andrew Burgess. And in this Tuts+ coffee course we're gonna take a look at the JSX syntax which is part of the React library. As you can see in this little code demo we got here we've got a couple of different instances of JSX. One right here in this Hello component we're creating. And then down here where we render Hello, we're also using JSX. And as you can see JSX kind of looks like HTML. I like to think of it as almost a new type of JavaScript primitive data type. It looks like HTML, it acts a lot like JavaScript. So let's see what we can learn about it. First of all we have components. For example, div here is a component, and so is Hello. As you can see, React comes with a bunch of components that refer to native HTML elements. We're using div here but there's also h1 and ul and li and all of the different HTML elements. We can use those but we can also create our own components. And that's what this Hello class that we're creating here is. It's our own Hello component. And when we use JSX down here to render Hello. What actually displays on the page is the HTML represented by the JSX inside of the component that we're rendering. So right now as you can see over here in our output section, we're just rendering Hello. But if we were to change this to be an h1 element and I was to rerun the page. Then you can see that Hello would be rendered in an h1 element. This isn't actually HTML but it renders to HTML. So we have these components here like h1 and Hello. And these components just like regular HTML elements can have children. They can have text as a child as we see here with Hello. They can have other components as a child. So for example we could nest an i element in here and give it the text World as its child. And so now we have a couple layers of nesting going on here. And when I run this you can see we have Hello World with world in italics. The other thing we can do is embed new values in here. So for example let's say in this render function we have a variable name inside of components or nested components. We can use curly braces to embed JavaScript expressions. So within curly braces here I can just type name. And now when I run this code you can see that we get the text Hello React. Now when you're embedding an expression like this you don't have to worry about escaping values. React will do that automatically for you. So what we can do is replace this name with a prompt. And now when I run this we get a prompt asking us for a name. And if I was to try and do something semi-malicious here by trying to embed some HTML. Notice that what happens is the HTML doesn't get run. Instead it gets escaped and we actually see those special characters being printed here. So you don't have to worry about user input messing up your application. Now if you don't want any content inside of an element you can just self close it. As you can see that's what we've done here where we rendered Hello. Now there's something else you might notice about the names of some of these components. All of the standard HTML element components that come built-in with React, in this case we're using h1 and i. They are all lowercase and you have to use them this way. However when you're creating your own custom components as we are doing here with Hello. They must begin with uppercase. And so React will know when we try and render Hello here. That this refers to our own element and not one of its native ones. And this is an opportune place to talk about what's going on behind the scenes here. Because of course the JavaScript engine in your browser is not natively rendering JSX. It needs to be compiled into a React function call first. If you go to the Babel compiler and try it out you can add the React preset. And then you can see we can write a simple function here with some JSX inside of it. And that will get compiled over here on the right. So you can see here we have the JSX for this div. On the right here you can see we have react.create element. Which is the react function call. This function, react.create element takes a couple of parameters. The first one as you can see is the element name or the type that we are using. In this case you can see it's div. Then we have any attributes. And we'll get to attributes in a second, but those are null in this case. And finally we have the children which come after that, in this case there's only one child, Hello. If we were to create a name here and I was to try and embed that name here. You can see that we actually get name as another child. And maybe let's put an exclamation point after name so you can see we have three children elements here. Hello world, the name, and then the final exclamation point. And so to come back to the main point here. Notice that when we use the div element. Div here is a string because it doesn't refer to an object. It refers to something internal. And this div string lets the react.create element function know to use its own component. However, let's copy our Hello component here and I'm going to paste it in here. So you can see here we have our Hello class. And now down inside of this Hello function, let's go ahead and render Hello. Now on the right here, if we scroll down to the bottom. You can see that inside of our React.createElement call where we create the div. One of the child elements of this is another React.createElement call. But notice this time, the element is Hello and this is not a string because it refers to an actual object. If we scroll back up to the top here, you can see where our Hello instance here is React.createClass. So we create that component by passing it in to React.createElement. So you can see when we create a component and then render it like this in JSX. Behind the scenes, it's just getting turned into a regular JavaScript function call. And so this means there are a few things to know about naming your components. For example, we can create a component that is a property on an object. For example, if I were to create an object here called Comps for components. And then we were to do Comps.Hello. And that's how we assign this. Then down here I can say Comps.Hello. And of course this has no problem rendering because it can access that property just fine. What we can't do though is use the square brackets syntax. If I try and reference the Hello component using the square brackets syntax we get a complaint. Now you might want to do something like this. Because when the actual component name is a string in this way. That means you can decide at runtime what component you want to render. And this gives you a little more freedom in rendering your app. However because these are just values what we can do is call this CompToRender. And that's going to be Comps['Hello']. And we basically just assign it to a new variable. Making sure of course that it starts with an uppercase letter. And then we can just do CompToRender and we have no problem. Down here in Hello the exact same thing happens. We just reference this in a variable. And then we can reference that variable instead of doing the square bracket syntax directly. Another thing to remember is that whenever you write a chunk of JSX. It is a JavaScript expression. And therefore we can't really return two elements that are side by side. For example, if I have a div here that says hi and a div here that says bye, notice that we have an error. The compiler says that adjacent JSX elements must be wrapped in an enclosing tag. For this to work, we need to wrap our two divs in an enclosing div. That way, we're only returning a single expression instead of two expressions. And of course you can return a single expression from a JavaScript function. Now since everything is an expression that means we have a lot of flexibility when rendering elements. Let's come back to JSFiddle here for a second. And let's say instead of a set of names I have a list that I want to render. Of course what we want to do here is return an unordered list. But what are we going to do inside of this? How can we loop over our list? Well let's start by doing it this way. Let's create a variable called listEls. And we'll do and we'll map over each item in the list. Inside this list let's just return a JSX expression. So, we have a list item here, and as the child here we'll just put the item as the child. And so now we have mapped our list of values into a list of JSX values. And so, now, we can just use the curly braces to embed those JSX elements into our JSX structure. So, if I click Run Now, you can see that we have a list with a, b, and c. Now, really, we didn't even have to store this in a variable first. I can just copy this expression here because is an expression, right? It returns a value. And therefore I could just paste this expression right in here. We can get rid of that entirely. And now if I run this you'll see that we have exactly the same output. Now there is one small thing that we need to worry about here. And if we pop open the console we can see there's a warning here. Each child in an array or iterator should have a unique key prop. Basically the problem is that we have three list items here rendering side by side. And React doesn't know how to tell them apart. The problem with this is that if the state changes in our application and we need to rerender this list. React will need to know which items it needs to rerender and so it needs some way to reference those. So what it wants us to do is add a key property to each list item. So here we'll add a key prop. Now we haven't really talked about properties or attributes yet but this is how we can do this. We have the key as the value name. And then we can use our curly braces once again to embed a value as the value of that key. In this case, we're just going to use item. And of course if I rerender this, you can see that the list looks the same, but this time the error is gone. In this case we just used the item itself as the key, and really any unique identifier would be fine. React recommends that you do item.toString if that will produce a unique identifier for your item. Otherwise a lot of the time you're getting a list of items from a database. And so you might have something like id as a property and you can use that to provide a unique identifier. If all else fails when you're mapping like this you get an index and so you could use that index as your key. One more thing about rendering components. JSX is all about expressions. And so this means you can't use an if statement or a for loop inside of your JSX. Now of course as we've seen map takes the place of a for loop. But what about replacing if? Let's say we have a variable here called displaytoolbar. And display toolbar here is either going to be true or false. Of course this probably won't be a variable like this. It will probably be a property passed in. But let's work with it like this for now. How can we look at this Boolean and decide whether or not to render our toolbar inside of this? Well we could do this a couple of ways. We could say var toolbar is going to be null. Or we could also use false or undefined or even true, really. Any Boolean value or null or undefined. React will just not render if we put it inside the expression. So if we were to do something like this now, toolbar, we would see absolutely nothing on the page. So then underneath this we could say if(displayToolbar) is true then we can set toolbar. And in this case I'll just set it to the string toolbar. But ideally we would have a toolbar component. So since toolbar here is true you can see we have the text toolbar. If we switch this to false and render this again you can see the toolbar is no longer displayed. However, there are other ways we can do this too. Because the ternary expression is just that, an expression, we could use that. So we could say displayToolbar. If that is true we will display toolbar, in this case the string. Otherwise we will just display null. So now if we run this again we get nothing. And if I change displayToolbar to true now the toolbar is displayed. Of course an even shorter way would be to just say displayToolbar && 'toolbar'. And that way if this is true, the second part will be run. If it's false, the second part will not be run. So if we do this, we get to two toolbars showing up on our page. There's one more thing to mention about JSX in components. And that is receiving children into a component. Right now we're just rendering Hello as a self-closing element. But what if instead we rendered Hello with a name inside of it? Is there some way we can use this name? Well, actually there is. We can reference the children of an element from within that element's render function through this.props.children. What we could do is inside of this div, just say Hello and then we render this.props.children. And now if I run this you can see that we get the text Hello Andrew. Now the other part of JSX which we haven't talked about yet is properties. If we come back to the Babel compiler for a second you can see that we're recalling React.createElement. The second argument here to this function is null. And that's because this div that we're trying to render doesn't have any attributes. However if I were to add an id of main to this div you can see that instead of null we pass an object. Which is of course a set of key value pairs. Now just like we can use curly braces to embed children into a component. We can also use curly braces to embed a value to an attribute value. Or as React calls them, props or properties. We could say var name = andrew. And I can use curly braces to set the id equal to that value. And as you can see here in our rendered version this just references the name variable. Now in HTML, we can use hyphenated attributes. And we can do the same in React. As you can see my-name hyphenated just gets wrapped in quotes. However this is not really the convention. In React, since JSX is very much like a JavaScript expression, the convention really is to use camel case. And to say myName instead of my-name. There are a few values that you cannot use as a property name. But React is really good about loudly complaining about these. One example of that is class. Although you can see it's working here. If we were rendering with React and not just compiling. It would say that class is a protected word in JavaScript. And therefore you shouldn't really use it that way. Instead, to assign a class to an element you use className. Another one that I've run into a lot of times is if you're adding the for attribute to a label. So that it will be connected to the related input. Instead you have to do htmlFor. And of course both className and htmlFor are famel case. If we were to add a property with no value. For example on an input, you might have checked, if it's a checkbox, it will default to true. Notice over here we have checked equals true. And finally if we had an object that we wanted to use as properties. And now we wanted to apply both of these as properties to our div here. We can use the expression syntax. And we can use the spread operator. So we can say ...props. And that will spread out the props object as the properties of this element. And of course notice we can include other properties as well. If you see in the compiled version basically it just extends a new object with those properties. And then with any that we add manually. Actually if we took checked off, you would see its even shorter syntax. It just uses that props object, as the set of properties that we apply. If you haven't used JSX much, I realize that I've just thrown quite a bit of information at you. But really once you get some practice under your belt I think you'll find that using JSX isn't much more difficult at all. I'll admit that initially I was quite skeptical about it as well. But the more I've used it the more I found that it's actually a very flexible syntax addition to JavaScript.

Back to the top