3

Components in React

Components are one of the pieces that make React, well, React! They’re one of the primary ways you have for defining the visuals and interactions that make up what people see when they use your app. Let’s say Figure 3.1 shows what your finished app looks like.

An illustration of the finished app is shown. The name of the app is displayed at the top-left, a search bar is present at the top-right, and various thumbnails that represent the contents on the app page are present below this.

Figure 3.1 Your hypothetical finished app.

This is the finished sausage. During development, viewed through the lens of a React project, things might look a little less appealing. Almost every part of this app’s visuals would be wrapped inside a self-contained module known as a component. To highlight what “almost every” means here, take a look at the diagram in Figure 3.2.

An illustration shows the various components of the app highlighted using dotted lines. Pointing to this, a label reads the text "That's a lot of components."

Figure 3.2 Diagrammatic representation of the app components.

Each dotted line represents an individual component that is responsible for both what you see and any interactions that it is responsible for. Don’t let this scare you. While this looks really complicated, you will soon see that it will start to make a whole lot of sense once you’ve had a chance to play with components and some of the awesome things they do—or, at least, try really hard to do.

Quick Review of Functions

In JavaScript, you have functions that enable you to make your code a bit cleaner and more reusable. Now, there’s reason we’re taking some time to look at functions, and it isn’t to annoy you! Conceptually, functions share a lot of surface area with React components, and the easiest way to understand what components do is to take a quick look at functions first.

In a terrible world where functions don’t exist, you might have some code that looks as follows:

In a really chill world that involves functions, you can condense all that duplicated text into something simple, like the following:

Our getDistance function removes all the duplicated code you saw earlier, and it takes speed and time as arguments to allow you to customize the calculation that gets returned.

To call this function, all you have to do is this:

Doesn’t this look nicer? Functions provide another great value, too. Your functions (such as the alert inside getDistance) can call other functions as part of their running. Take a look at using a formatDistance function to change what getDistance returns:

This capability to have functions call other functions enables us to cleanly separate what functions do. You don’t need to have one monolithic function that does everything under the sun; you can distribute functionality across many functions that are specialized for a particular type of task.

Best of all, after you make changes to how your functions work, you don’t have to do anything extra to see the results of those changes. If the function signature didn’t change, any existing calls to that function will just magically work and automatically pick up any new changes you made to the function itself.

In a nutshell, functions are awesome. I know that. You know that. That’s why all of the code we write has them all over the place.

Changing How We Deal with UI

I don’t think anybody will disagree with the good functions bring to the table. They really make it possible to structure the code for your apps in a sane way. That same level of care we use in writing our code isn’t always possible when it comes to writing our UIs. For various technical and nontechnical reasons, we’ve always tolerated a certain level of sloppiness with how we typically work with our UI elements.

That’s a pretty controversial statement, so let me highlight what I mean by looking at some examples. Let’s go back and look at the render method we used in the previous chapter:

Onscreen, you see the word Batman printed in giant letters, thanks to the h1 element. Let’s change things up a bit. Say that we want to print the names of several other superheroes. To do this, we modify our render method to look as follows:

Notice what you see here. We emit a div that contains the four h1 elements with our superhero names.

Okay, so now we have four h1 elements that each contains the name of a superhero. What if we want to change our h1 element to something like an h3 instead? We can manually update all of these elements as follows:

If you preview what we have, you’ll see something that looks a bit unstyled and plain (see Figure 3.3).

The superhero names: Batman, Iron Man, Nicolas Cage, and Mega Man are displayed one below the other in a plain fashion.

Figure 3.3 Plain vanilla superhero names.

We don’t want to go crazy with the styling here. All we want to do is italicize all these names by using the i tag, so let’s manually update what we render by making this change:

We went through each h3 element and wrapped the content inside some i tags. Can you start to see the problem here? What we are doing with our UI is no different than having code that looks as follows:

Every change we want to make to our h1 or h3 elements needs to be duplicated for every instance of them. What if we want to do something even more complex than just modifying the appearance of our elements? What if we want to represent something more complex than the simple examples we’re using so far? What we’re doing right now won’t scale; manually updating every copy of what we want to modify is time-consuming. It is also boring.

Now, here’s a crazy thought: What if everything awesome that we looked at about functions could somehow be applied to how we define our app’s visuals? Wouldn’t that solve all the inefficiencies we’ve highlighted in this section? As it turns out, the answer to that “what if” forms the core of what React is all about. It’s time for you to say hello to the component.

Meet the React Component

The solution to all of our problems (even the existential ones we grapple with) can be found in React components. React components are reusable chunks of JavaScript that output (via JSX) HTML elements. That sounds really pedestrian for something capable of solving great things, but as you start to build components and gradually turn up the complexity, you’ll see that components are really powerful and every bit as awesome as I’ve portrayed them.

Let’s start by building a couple of components together. To follow along, start with a blank React document:

Nothing exciting is going on in this page. As in the last chapter, this page is pretty barebones, with just a reference to the React and Babel libraries and a div element that proudly sports an id value of container.

Creating a Hello, World! Component

Let’s start really simple. We want to use a component to help us print the famous “Hello, world!” text to the screen. As we already know, using just the render method of ReactDOM would give us code that looks as follows:

Let’s re-create all of this by using a component. React gives us several ways of creating components, but we are going to create them by using the class syntax. Go ahead and add the following highlighted code just above the existing render method:

If the class syntax is foreign to you, first check out my online tutorial Using Classes in JavaScript (https://www.kirupa.com/javascript/classy_way_to_create_objects.htm).

Getting back to our code, we have created a new component called HelloWorld. This is a component because it extends React.Component. If it didn’t do that, it would just be an empty class that doesn’t do much. Inside our class, you can put all sorts of methods to further define what HelloWorld does. Some methods that you define are special, and React uses them to help your components work their magic. One such mandatory property is render.

Go ahead and modify our HelloWorld component by adding the render method, as shown:

Just like the render method you saw a few moments earlier as part of ReactDOM.render, the render function inside a component is also responsible for dealing with JSX. Let’s modify our render function to return Hello, componentized world!. Add the following highlighted line:

You’ve told the render function to return the JSX that represents the Hello, componentized world! text. All that remains is to actually use this component. You use a component after you’ve defined it by calling it. Here we call it from our old friend, the ReactDOM.render method.

The way you call a component from it is a bit unique. Go ahead and replace the first argument to ReactDOM.render with the following:

That isn’t a typo! The JSX we use for calling our HelloWorld component is the very HTML-like <HelloWorld/>. If you preview your page in your browser, you’ll see the text Hello, componentized world! showing up on your screen. If you were holding your breath in suspense, you can relax.

If you have difficulty relaxing after seeing the syntax we used for calling HelloWorld, stare at the circle in Figure 3.4 a few moments.

A simple, colored circle is shown. A text below the circle reads "Just relax and focus on this circle."

Figure 3.4 Just some lighthearted distraction!

Okay, back to reality. What we’ve done so far might seem crazy, but simply think of your <HelloWorld/> component as a cool and new HTML tag whose functionality you fully have control over. This means you can do all sorts of HTML-y things to it.

For example, go ahead and modify our ReactDOM.render method to look as follows:

We wrapped our call to the HelloWorld component inside a div element, and if you preview this in your browser, everything still works. Let’s go one step further! Instead of having just a single call to HelloWorld, let’s make a bunch of calls. Modify our ReactDOM.render method to now look as follows:

Now you’ll see is a bunch of Hello, componentized world! text instances appear. Let’s do one more thing before we move on to something shinier. Go back to our HelloWorld component declaration and change the text you return to the more traditional Hello, world! value:

Make this one change and then preview your example. This time around, all the various HelloWorld calls we specified earlier return Hello, world! to the screen. No need to manually modify every HelloWorld call—that’s a good thing!

Specifying Properties

Right now, our component does just one thing. It prints Hello, world! to the screen—and only that! That’s the equivalent of having a JavaScript function that looks like this:

Except for one very specific case, that JavaScript function doesn’t seem very useful, does it? To increase the usefulness of this function, we need to modify it to take arguments:

Now this function can be used more generally for a variety of situations, not just one whose output will be 42km.

Something similar applies to your components as well. Just as with functions, you can pass in arguments that alter what your component does. There’s a slight terminology update you need to be on top of. What we call arguments in the function world are known as properties in the component world. Let’s see these properties in action!

You’re now going to modify the HelloWorld component to allow you to specify who or what you greet besides the generic World. For example, imagine being able to specify Bono as part of the HelloWorld call and seeing Hello, Bono! appear onscreen.

To add properties to a component, you need to follow two parts of instructions.

First Part: Updating the Component Definition

Right now, our HelloWorld component is hard-coded to always send out Hello, world! as part of its return value. We first need to change that behavior by having the return statement print out the value passed in by a property. We need a name to give our property; for this example, we call our property greetTarget.

To specify the value of greetTarget as part of our component, we need to make this modification:

You access a property by referencing it via the this.props property that every component has access to. Notice how you specify this property: You place it inside curly brackets, { and }. In JSX, if you want something to get evaluated as an expression, you need to wrap that something inside curly brackets. If you don’t do that, you’ll see the raw text this.props.greetTarget printed out.

Second Part: Modifying the Component Call

After you’ve updated the component definition, all that remains is to pass in the property value as part of the component call. This is done by adding an attribute with the same name as the property, followed by the value you want to pass in. In our example, that involves modifying the HelloWorld call with the greetTarget attribute and the value you want to give it.

Go ahead and modify the HelloWorld calls as follows:

Each HelloWorld call now has the greetTarget attribute, along with the name of a superhero (or equivalent mythical being) that we want to greet. If you preview this example in the browser, you’ll see the greetings happily printed out onscreen.

One last point is important to call out before we move on. You are not limited to having just a single property on a component. You can have as many properties as you want, and your props property will easily accommodate any property requests you have without making any fuss.

Dealing with Children

A few sections ago, I mentioned that components (in JSX) are very similar to regular HTML elements. You saw that when you wrapped a component inside a div element or specified an attribute and value as part of specifying properties. Just as you can have many HTML elements, your components can have children.

This means you can do something like this:

Here you have a component very cleverly called CleverComponent, and it has a p element as a child. From within CleverComponent, you have the capability to access the p child element (and any children it has) via the children property accessed by this.props.children.

To make sense of all this, let’s look at another really simple example. This time around, we have a component called Buttonify that wraps its children inside a button. The component looks like this:

You can use this component by calling it via the ReactDOM.render method, as shown here:

When this code runs, given what the JSX in the Buttonify component’s render method looked like, you see the words SEND DATA wrapped inside a button element. With the appropriate styling, the result could look comically large, as in Figure 3.5.

A figure shows a button "SEND DATA" that appears big. A text, pointing to the button, reads "Why is this button so big?"

Figure 3.5 A large Send Data button.

Getting back to the JSX, notice that we specify a custom property called behavior. This property allows us to specify the button element’s type attribute, and you can see us accessing it via this.props.behavior in the component definition’s render method.

There’s more to accessing a component’s children than what you’ve seen here. For example, if your child element is just some text, the this.props.children property returns a string. If your child element is just a single element (as in our example), the this.props.children property returns a single component that is not wrapped inside an array. We still need to call out a few more things, but instead of enumerating all the cases and boring you, we’ll bring up those points later as we look at more elaborate examples.

Conclusion

If you want to build an app using React, you can’t wander too far without having to use a component. Trying to build a React app without using a component is kind of like building a JavaScript-based app without using functions. I’m not saying that it can’t be done; it’s just one of those things you don’t do—kind of like the Bad Idea part of the popular Animaniacs Good Idea/Bad Idea sketches (https://www.youtube.com/watch?v=2dJOIf4mdus).

If this witty video doesn’t convince you that you should learn to embrace components, I don’t know what will—except for maybe a future chapter on creating complex components!

Note: If you run into any issues, ask!

If you have any questions or your code isn’t running like you expect, don’t hesitate to ask! Post on the forums at https://forum.kirupa.com and get help from some of the friendliest and most knowledgeable people the Internet has ever brought together!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.149.32