Building the Greeting App

Now that we've introduced our very first app, the Greeting App, this lesson will cover the actual building of it, step by step.

Building the Greeting App#

Introduction#

Hello and welcome to our very first React demo, as part of the Beginner's Guide to Real World React course.

The first real example we're going to build is a really simple greeting app that’s going to accept a name in an input box and output it back as part of a welcoming message.

Adding Parcel bundler#

Now you can just use React by loading it using a script tag from a package repository like unpkg. However, what you'll find with most real-life React projects is they will be adding the React libraries over npm and usually using some sort of code bundler such as Webpack, or even the Create React App starter project (which uses Webpack under the hood).

We're going to do something similar so you get familiar with using a common means to build and run a React project. For this, we’re going to use Parcel JS.

Parcel JS is a really simple code bundler that’s very much like Webpack but without a lot of the complex configuration and setup. In its own words Parcel JS is a ‘blazing fast, zero-config web application bundler’.

You’ll see I’ve got the Parcel JS website open (https://parceljs.org) and we’re going to head over to the ‘getting started’ section. We need to install it globally onto our machine and you can do that by using the commands on this page:

npm i -g parcel-bundler

Or

yarn -global add parcel-bundler

Once you've done that, we'll close this window up and we'll open up a brand new project in VS Code.

Adding React to the project#

We’ve got a shiny new, empty folder that we’ve opened in VS Code. I’ve got a .gitignore file and a readme in here because I’ve got this connected with a git repository, but we’re not going to use those files and you can ignore them.

Because we’re using Parcel, we don’t need to do any configuration to make it work, but we do need to add React to our project.

Open up your terminal in VS Code and you’ll see that it’ll open in the current working directory of our project. From here, we’re going to do three steps to get our project up and running with everything we need:

  1. Initialize our project

  2. Add the React dependencies

  3. Add a shortcut script to build and run our code

Initialize the project#

The first step is to initialize our project with a package.json file. To do that we’re going to run the command:

yarn init -y

We add the -y flag which will automatically answer yes to all the initialization questions such as, ‘who's the author?’, ‘what's the license?’, and those sorts of questions that we don’t care about for our example.

Add React dependencies#

Next, we're going to add React to the project. There are two packages we need, React, and React DOM. React is the star of the show and includes the core React library. React DOM is a secondary package that is responsible for rendering our components to the DOM in the browser.

Back in our terminal type the following command to add both packages to the project:

yarn add react react-dom

Yarn is well cached and very fast so both of those packages should be added to the project in no time at all.

Add scripts for building and running the code#

The final part of our setup involves the package.json file. Notice the react and react-dom dependencies in there.

Now, once we’ve built our app, we need to call Parcel to bundle everything up and run it. It’s not a huge chore, but we can add a simple shortcut to help us out.

In our package.json file, add a new property, ‘scripts’ and add a new command property under this and call it ‘start’. Next, add the command:

parcel index.html —open

The new part of the package.json file should look like this:

What we’ve just written there is a terminal shortcut that will allow us to type yarn start and have our Parcel command open our starting file, and the --open flag tells Parcel to open the running code in a browser once the files have been compiled and Parcel’s development server is up and running.

Parcel works by giving it an entry point, in this case, our index.html file which we’ll be building next. From there, Parcel works out which files it needs to include in the bundle based on your imports and file references.

Coding the project files#

Now onto the exciting part: building out our example. Now for smaller projects like this, I like to just start by creating all the files we need and then filling them in as we go along.

For our greeting app, we're going to need to create four files. So let's create them now. We'll need:

  • A styles file, called styles.css. We'll just have some basic styles in there just to make our app look slightly more interesting than the out-of-the-box HTML.

  • Our Parcel starting point, index.html. This is going to be the very first entry point that Parcel is going to look for to render our app.

  • A starting point for the JavaScript, which will be index.js.

  • And finally, our main React component, which we'll call app.js. This is our main entry point for the React side of things.

Once we have the files created, it’s time to fill them in. Starting with our styles.css file.

Styles.css#

Our styles file isn’t absolutely essential at this point, but it’s nice to have a few basic styles available to improve the built-in look and feel that browsers give us by default.

You can see I've copied and pasted some really simple styles in there that just affect the body, the font size, and the line-height. Later on, we’ll be adding an input and a button to our app, so I’ve also added some nice styles for those.

Give that a save and we’ll move onto our entry point, our index.html file.

Index.html#

The next thing we want to do is add some HTML to our index.html file. I'm using Emmet that comes with VS Code, because it allows me to type the name of the HTML elements, like ‘head’ or ‘title’ and hit the tab key, and Emmet will handily just output the complete HTML element’s tag for us, rather than having to type it all out by hand. It’s a nice little timesaver.

So we’ll add the HTML tag first. Inside that we’ll add a <head> tag, and within that, we’ll add a <title> tag and I’m going to give it a title of ‘My first React example’.

We’ll also need a <body> tag, so we’ll add that. Within the <body> tag, we need two things:

  • Some kind of element to render our React output into.

  • And a script tag that references our JavaScript entry point, index.js (which we’ll create once we’re done here).

For the first one, I'm going to add a <main> element and give it an ID of ‘output’. Finally, we’ll add our <script> tag that references index.js.

What happens here is that when Parcel runs, it looks in this file first for any script tags. When it finds this one pointing to index.js, it looks in there to see what other JavaScript files it needs to import and chain together to bundle up into our working app.

With that done, we’ll save the file and move on to the main JavaScript entry point, the index.js file.

Index.html contents#

Index.js#

Inside our index.js file is where the magic happens. It’s the first place that we really set up our React app to load and inject it into our HTML page. This is going to be quite a small file where we’ll add our very first piece of React code.

We’ll need to do a few things inside this file:

  • Import React

  • Import our main App component, the starting point for our React app

  • Use React DOM to render our App to the browser

Importing React and the App component#

First off, we’ll need to import two React packages: React and React DOM. So let’s do that now

It's important to note that whenever you're doing anything with React, you must import it at the top of the file. This is what’s known as bringing React into scope. For this file, we also need the React DOM package, which is responsible for rendering our React code to the browser.

Finally, we'll import our App component, which will look after greeting the user.

Now we have all of our imports we need to make sure our app gets rendered out to the browser. To do that, we call the render() method from the React DOM package that we imported.

ReactDOM.render() accepts two arguments:

  • The component that you want to render (for us, that’s APP).

  • And where you want to render it, i.e. the HTML element from the index.html file.

To add our App component into the ReactDOM.render() method, we’ll get our first glimpse of JSX, React’s XML-like syntax. It looks very similar to XML or HTML and indeed, later on, we’ll be adding paragraph tags and input elements into our components, but it’s important to know the difference. What we’re using here is JSX which is propriety React syntax.

For the second part, I'm going to use the built-in document.querySelector() method to find the <main> element we created in our index.html file. We gave it an ID of output so we’ll use that here to find it.

Save the file and that’s us done. Onto our App component.

App.js#

Notice that the name of the file has been capitalized to ‘App.js’. This is not 100% necessary, but it’s a convention used among React projects to capitalize any component file names.

The last piece of the puzzle is to build out our App component to make something happen and greet our users.

As we've already discussed, if we're using React, we need to have React in scope, so we’ll import React at the top of the file.

Scaffolding the app#

What I like to do once we've done that, is just outline the basics of the component and then export that component so it can be used in another file, or another component.

It will look like this:

For now, we're going to use a class-based component, which is an older, less-preferable means to build components. However, you’ll see some of them out in the wild, so it’s useful to take a look at how they’re built. For future lessons, we’ll be using the more modern functional components with React Hooks which look quite different.

For class-based components, we need to extend React’s Component class. We can do that by typing the extends keyword after our class declaration, and then extending the React.Component class in there.

To make this look a little neater, we can import the Component class as part of our React import at the top of the file. We’ll add it as a named import like this:

import React, { Component } from 'react';

By doing that, we can replace the React.Component part with just Component.

Finally, we want to add a default export for this component which is just App. We’ll add this right after our class declaration.

export default App;

We’re not quite finished yet, but we’ve got the building blocks in there. If we run this now, nothing would happen because our component doesn’t return anything.

Adding a title#

All React components have to provide some sort of return which is usually a block of JSX. With class-based components, we have to first provide a render() method and then add a return statement within that render() method.

To get us started and to test our app, we’ll just return a heading. Add a render() method, add a return statement within that and we’ll add a simple message using an <h1> tag.

Great! Head over to your terminal and type yarn start to start Parcel building and running our app. Parcel’s going to find our index.html file, follow it to our index.js file, this will load our App component and then Parcel will bundle that all up, optimize it and start a local development server that runs at http://localhost:1234.

The development server should start up and open a web page where we’ll see our lovely welcome message, ‘Welcome to the app’.

Another nice thing about Parcel’s local development server is that it hot reloads, responding to file changes on saving and refreshing the browser!

Preventing JSX errors with React fragments#

An important thing to note about JSX is that you can only return one top-level element. To highlight this, if we type a paragraph tag in here and say ‘this is a paragraph’, and click save, you'll see that we get a nasty error message.

JSX error

The error message states ‘Adjacent JSX elements must be wrapped in an enclosing tag. Did you want to use a JSX fragment?’

You can see we’ve got two adjacent, top-level elements in our return statement. To fix this, we need to wrap these elements in a containing element. We can wrap them in a div and click save.

When the app reloads we’ll see our message and paragraph and, more importantly, no error.

Adding a div element is fine for our example here, but you might have situations where you don’t want additional markup output to the browser, and wrapping everything in a div or some other element won’t be sufficient.

For these cases you can use the React.Fragment syntax. We can replace our containing div element with either the React.Fragment syntax or its shorthand:

However, the shorthand version looks a lot neater and cleaner. We’ll be using this version wherever it’s needed.

React and the DOM: React uses its own copy of the DOM which is called the Virtual DOM. React handles changes to this internal copy of the DOM and the real DOM in the browser for us to keep everything in sync. Although JSX looks almost identical to the same HTML we’d type into a .html file, it’s important to understand that it doesn’t map directly to the HTML that’s eventually output to the browser.

Adding a dynamic message#

Time to expand our app. In the first paragraph, we're going to return our user's name once they’ve typed it in. To do that we need to modify our paragraph tag to include some executable code.

If you did this in HTML, you’d just get a paragraph with the text, ‘Hi there, {this.state.displayName}’, but because we’re using JSX, anything between the curly braces will be interpreted as executable JavaScript by React and evaluated as such.

You’ll also notice a call to a class property called state. Each component has access to its state and its local storage. You can store values in a state as well as retrieving them, which is what we’re doing here.

So our line, {this.state.displayName} is really saying ‘get me the displayName value out of this component’s state’.

We haven't added our state yet, so let’s do that now.

Adding state to our app#

Within a class-based component, just like a regular JavaScript class, you’ll want to initialize any state values in the constructor.

React automatically wires up our constructor when the component is created and it passes it a properties object, called props for short (you’ll see this a lot when dealing with React).

The first thing we have to do in our constructor is call the parent class’ constructor (the parent class is the Component class that we extended right at the beginning) using super method, passing in the props object.

To add our component’s state property, we simply call this.state and set it to an object that contains whatever data you need it to. For now, we’ll just add the displayName property and set it to an empty string.

An important thing to note about state is that it is immutable. This means that whilst it can be updated by using React’s setState() method, we never edit state directly. The only time you’ll ever set state directly is in a constructor.

You don’t have to initialize state in the constructor as we’re doing here, but it’s a good habit to get into so that anyone coming into the class can see what properties should be expected to exist on the state object, and what their values or their types should be.

Handling user input#

We’ve got our dynamic welcome message but we need to allow the user to enter their name so we can greet them personally.

Let’s add some instructions and an input box:

We’ve set our input’s value to another state value, {this.state.name}. By doing this we're turning it into what’s known as a controlled component. HTML form elements like inputs, selects, and text areas are typically uncontrolled components because they handle their own state and values.

However by letting React handle our input’s value from state, it becomes a controlled component which means that React is responsible for maintaining the state of any value that we assign to it.

Since we’ve added a new state value reference here, let’s update our component’s state in the constructor:

If we stop there, however, the value of the input will always be an empty string. We need a way to update this value in state whenever someone updates the text.

We do that by adding an event handler to the input element. The perfect place to do this update will be as part of the onChange event, which fires every time the text in the input changes.

Add the onChange event to the input and add a handler function, handleChange which we’ll define next.

Now, we’ll define the handleChange event. Add it before the render() method in our class.

The handler function is a simple arrow function that accepts one argument, which is an event object that React automatically passes in for us (also known as a synthetic event). I’m calling it evt here, but you might see it called e or event.

In this function, we just need to update our state’s name value with whatever text our user has entered. To do that, we’ll use React’s built-in state updating method, setState().

We’ll call setState() and pass it an object that contains any property:value pair that we want to update in state. In our case, we want to update the name property with a value of our text input which we can grab from the evt argument using evt.target.value.

Triggering a greeting with a button#

In order for this to really be a true app, we’ll give our users some way to trigger a greeting message update once they’ve updated their name in the input box.

To do that, add a button just under our input with a similar event handler, but this time the event will be onClick instead of onChange. We’ll also give it some text, ‘Update name’:

The onClick event is very similar to onChange and again it’ll receive a synthetic event argument that we’ll just call evt once more.

You can see our click handler method is doing the same update to state by calling the setState() method, but this time we’re updating our displayName value.

The displayName value is going to be the same as the final value they’ve entered in the input box, which we’ve already set to the state value, name. So that’s what we’ll use to update state within our handleClick method.

The complete App.js file#

When complete, your App.js file should look like this:

Testing our greeting#

Now that we’ve got everything we need, save our App.js file, and let’s take a look in the browser. If we enter a name into the input box and click ‘Update name’.

You can see that instead of ‘Hi there ’, we’ll get ‘Hi there, Rob Kendal’ (or whatever you entered).

Finishing touches#

The very last part of our Greeting App is to just add a little spit and polish. Remember those styles we added right at the start? Now, we’ll add them to the app by importing them just before the class component:

Give that a save and take a look in the browser. It’s not an award-winning app just yet, but you can see it looks a lot better already.

Last but not least, we have an initial message, ‘Hi there, ‘ and then just nothing. We can make this a little more interesting by adding in a default message ’we haven’t been introduced’.

We’ll do this by amending our initial greeting message using a logical OR statement. This sounds quite fancy, but it’s really a shorthand if statement in JavaScript that you’ll see used a lot in React to say ‘evaluate both sides of this argument and return whichever is true’.

Because our state value this.state.displayName is empty (false) by default, React will look at this and return the right-hand side of the argument, our default string.

And that's it. That's our simple very first foray into building a React app.

In the next lesson, we’ll refactor our App component into smaller components and introduce some React Hooks.

Please select a discussion on the left.