This video is available to students only

Refactoring the Greeting App

With our Greeting App built, we're going to learn how to 'think in React' by breaking down our small App into components and refactoring it to use them.

Refactoring the Greeting App#

We’ve built our first app and it’s looking and working great. Currently, it’s using the class-based component approach, but we’re going to refactor it to achieve a few things:

  • Get used to thinking about our apps in a component, modular fashion

  • Try our hand at breaking down a larger component into smaller ones

  • Introduce the arguably more common functional component approach to building our React components

At the moment we've got one large class-based component with all of the different things going on, including our event handlers for on change and on click. We’ve got a dynamic greeting and a title in there too.

It's not a very large component, but you can see how easily it could get out of hand as we add more and more features and functionality to it. It’s not very modular and it’s certainly not very reusable.

It's good practice to analyze your components and try to break them down into smaller ones where possible and where it makes sense. This way, you will encapsulate functionality into smaller working parts that can be duplicated and used in different places throughout your app.

Thinking in components#

It’s useful to look at a larger component as a whole and then think about smaller, independent parts of functionality that it contains. These smaller moving parts can be broken down into other components and used elsewhere; they’ll no longer be tied to this single, larger containing component.

To do that with our App component, we can look at what it’s currently doing and see that there are three distinct functions that it performs that would be good candidates to be turned into separate components:

  1. Displays a welcome message in a heading level one tag: This could have different styling applied to it in different parts of the app, or accept different messages on different pages, so it’s a good fit to be separated.

  2. Displays a dynamic message to the user including data from state: This greeting is quite simple and generic, and you may see it on the home page, or in the main navigation, say, of an e-commerce site to greet whoever’s logged in.

  3. Accepts input from the user and triggers an event on click of a button: We’re using the input and button combination here to accept a name, but it might also work on a contact form, or as part of a search form. Being able to have these two connected elements in one place, in a separate component makes it a great candidate for refactoring now.

Here’s a diagram of how we can group these separate areas of functionality into independent components: Title, Greeting, and Input. These child components can then be imported into their parent, the App component.

Demo component breakdown

Planning out the refactor#

We have an idea of the components we need to build and now we just need a set of steps to carry out our refactoring work.

Those steps might look like this:

  • Create a components folder to hold our new components

  • Create three new components

    • Title

    • Greeting

    • Input

  • Refactor the App component to use our new components

  • Refactor the App component from a class-based one to a functional component

Refactoring setup#

Now we have a plan, we’ll need to do some quick setup work before we start. Like we did in the last lesson, we’ll create all of the files that we need first and fill them in as we go along, building out the components and refactoring them as we go.

First, let’s add a new folder, and we'll call it components. Within our /components folder, we’ll create three empty component files with the .jsx file extension (remembering to capitalize the first character in the file name):

  • Title.jsx

  • Greeting.jsx

  • Input.jsx

Files with the .jsx extension are specific to the React library and will typically contain the familiar HTML-like syntax that we’ve seen in earlier chapters. However, it’s important to note that this file extension is down to personal preference. JSX files will be converted into raw JavaScript by a tool such as Babel JS before being run in the browser. Some people prefer to have presentational components that just accept static data and display it, using the .jsx file extension to denote them as such. The important thing to remember is that you can use either .js or .jsx to name your files, there is no difference, only personal preference.

With that taken care of, let’s start moving through the files and building them out.

Title.jsx#

We’ll start by repeating our mantra:

React must be in scope in order to use it!

So we’ll import React first before we do anything else.

Instead of the class-based approach previously used for our App component, the Title component will be our very first functional one. We define a functional component as just that, a function.

However, rather than define a function and then set it as the default export afterward, we can do so in one line:

This is a nice style to have for smaller, less complex components, especially if they’re purely presentational, like here. However, if your components start to grow, or feature complex functionality that may cause bugs, it makes sense to define your function and assign it to a variable (i.e. a const) and then export it immediately afterward. This is because the React debugging tools struggle to identify components that are defined and exported in a single line as we are doing here.

You can see we have a default export which is a function that accepts a props object and uses an implicit return (that is without the return keyword and some JSX within parentheses). Because we’re not doing any other logic, manipulating state, etc. we’re just returning some JSX, we can use this implicit return to make things look a little neater and remove unnecessary lines of code.

And that’s it…sort of. We have a heading one being returned, but we have a fixed string in there, ‘Welcome to the app’. That’s fine for our Greeting App, but not very reusable if we wanted to have this component on another page that said something different.

We can make this title dynamic so instead of it being hardcoded to a string, we can use our curly brace syntax again and use a value that we can pass in via our props object.

However, we can take this another step further. Because we know we’re only passing in a title value via props, we can reference this value directly using object destructuring.

We know that props will expect and be passed a property called title, so by replacing props with some curly braces we can now start to directly name properties that we expect props to have. This, in essence, is JavaScript’s destructuring syntax and it’s really quite neat!

As well as replacing the props argument in our function, we’ll need to replace the {props.title} with just {title} too.

What we’re left with now that we’re done is a really simple, small, reusable component. It can be used wherever we need across our app in different areas. It’s also useful if you need to make changes to the way titles look, such as styling, size, color, tag attributes; all those changes can be made in this one, single place.

The thing to remember is what we're making here is a very contrived example just to get a feel for React, but it's good to start thinking in terms of how you can use this in real world applications as you start learning and growing and building things for yourself.

This is something we'll do further on in the course as our apps start to grow and get bigger. But for now, this is our title component ready to go.

Completed Title component#

Here’s our finished Title component:

Greeting.jsx#

The next thing we're going to do is tackle the greeting message from our App component:

You can see we’ve got a paragraph tag with a string and a ‘displayName’ value we’re getting from state. We can pull this out into our Greeting component.

Start by importing React:

Again, just like our Title component, we're going to do an inline default export next, along with an implicit return, because all we're doing is returning one line which is going to be our greeting with a dynamic name value.

Notice that we can also repeat the destructuring syntax here to pull out the name value from props. The difference this time is that we’re going to add a default value for the name variable, just in case it’s not set.

You can happily do the same as we had in our app, {name || “we haven’t been introduced”} using the logical OR operator, but I find this way a little neater. I’ll leave it to you to choose as they would both produce the same result.

And that’s Greeting component built.

Completed Greeting component#

Here's our complete Greeting component:

Input.jsx#

The penultimate thing to build is our combined input and button component. This one's going to be slightly larger, but still not very complex.

We’re going to import React into our component, to begin with, but this time we’re also going to add a little extra named import useState.

Because our input element relies on our App component’s state to keep track of its value, we need to use state in our new Input component. Problem is, the Input component is a stateless, functional component, not a class-based one. In order for us to use some form of state in a functional component, we’ll need to use a feature of React called Hooks. In our case, to access state from a functional component, we'll use the useState Hook.

Hooks were introduced as part of React v16.8. They allow access to state and other React features without writing a class. We'll be covering Hooks in greater detail in the next module, including useState, but for now, focus on getting the components built as you follow along and become familiar with the useState syntax for accessing state in a functional component.