
Dedicated to my lovely wife, Jacqui Griffyth.
(And also to Peanut.)

is an experienced IT professional who has held senior positions in a range of companies, most recently serving as chief technology officer and chief operating officer of a global bank. Now retired, he spends his time writing and long-distance running.
is a senior consultant and a senior analyst/developer using Microsoft technologies. He works for BluArancio ( www.bluarancio.com ). He is a Microsoft Certified Solution Developer for .NET, a Microsoft Certified Application Developer for .NET, a Microsoft Certified Professional, and a prolific author and technical reviewer. Over the past ten years, he’s written articles for Italian and international magazines and coauthored more than ten books on a variety of computer topics.
The best way to get started with React is to dive in. In this chapter, I take you through a simple development process to create an application to keep track of to-do items. In Chapters 5–8, I show you how to create a more complex and realistic application, but, for now, a simple example will be enough to demonstrate how React applications are created and how the basic features work. Don’t worry if you don’t understand everything in this chapter—the idea is to get an overall sense of how React works. I explain everything in detail in later chapters.
If you want a conventional description of React features, you can jump to Part 2 of this book, where I start the process of describing individual features in depth. Before you go, make sure you install the development tools and packages described in this chapter.
There is some preparation required for React development. In the sections that follow, I explain how to get set up and ready to create your first project.
The tools used for React development rely on Node.js—also known as Node—which was created in 2009 as a simple and efficient runtime for server-side applications written in JavaScript. Node.js is based on the JavaScript engine used in the Chrome browser and provides an API for executing JavaScript code outside of the browser environment.
Node.js has enjoyed success as an application server, but for this book it is interesting because it has provided the foundation for a new generation of cross-platform development and build tools.
It is important that you download the same version of Node.js that I use throughout this book. Although Node.js is relatively stable, there are still breaking API changes from time to time that may stop the examples I include in the chapters from working. The version I have used is 10.14.1, which is the current Long-Term Support release at the time of writing. There may be a later version available by the time you read this, but you should stick to the 10.14.1 release for the examples in this book. A complete set of 10.14.1 releases, with installers for Windows and macOS and binary packages for other platforms, is available at https://nodejs.org/dist/v10.14.1 .
The create-react-app package is the standard way to create and manage complex React packages and provides developers with a complete toolchain. There are other ways to get started with React, but this is the approach that best suits most projects and is the one that I use throughout this book.
The Git revision control tool is required to manage some of the packages required for React development. If you are using Windows or macOS, then download and run the installer from https://git-scm.com/downloads . (On macOS, you may have to change your security settings to open the installer, which has not been signed by the developers.)
This command prints out the version of the Git package that has been installed. At the time of writing, the latest version of Git for Windows and Linux is 2.20.1, and the latest version of Git for macOS is 2.19.2.
Name | Description |
|---|---|
Sublime Text | Sublime Text is a commercial cross-platform editor that has packages to support most programming languages, frameworks, and platforms. See www.sublimetext.com for details. |
Atom | Atom is an open-source, cross-platform editor that has a particular emphasis on customization and extensibility. See atom.io for details. |
Brackets | Brackets is a free open-source editor developed by Adobe. See brackets.io for details. |
Visual Studio Code | Visual Studio Code is an open-source, cross-platform editor from Microsoft, with an emphasis on extensibility. See code.visualstudio.com for details. |
Visual Studio | Visual Studio is Microsoft’s flagship developer tool. There are free and commercial editions available, and it comes with a wide range of additional tools that integrate into the Microsoft ecosystem. |
The final choice to make is the browser that you will use to check your work during development. All the current-generation browsers have good developer support and work well with React, but there is a useful extension for Chrome and Firefox called react-devtools that provides insights into the state of a React application and that is especially useful in complex projects. See https://github.com/facebook/react-devtools for details of installing the extension. I used Google Chrome throughout this book, and this is the browser I recommend you use to follow the examples.
Projects are created and managed from the command line. Open a new command prompt, navigate to a convenient location, and run the command shown in Listing 1-6 to create the project for this chapter.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
The npx command was installed as part of the Node.js/NPM package in the previous section and is used to run Node.js packages. The create-react-app argument tells npx to run the create-react-app package that is used to create new React projects and was installed in Listing 1-3. The final argument is todo, which is the name of the project to create. When you run this command, the project will be created, and all of the packages required for developing and running a React project will be downloaded and installed. The setup process can take a while because there are a large number of packages to download.
When you create a new project, you may see warnings about security vulnerabilities. React development relies on a large number of packages, each of which has its own dependencies, and security issues will inevitably be discovered. For the examples in this book, it is important to use the package versions specified to ensure you get the expected results. For your own projects, you should review the warnings and update to versions that resolve the problems.

The project structure
Name | Description |
|---|---|
public/index.html | This is the HTML file that is loaded by the browser. It contains an element in which the application is displayed and a script element that loads the application’s JavaScript files. |
src/index.js | This is the JavaScript file that is responsible for configuring and starting the React application. I use this file to add the Bootstrap CSS framework to the application in the next section. |
src/App.js | This is the React component, which contains the HTML content that will be displayed to the user and the JavaScript code required by the HTML. Components are the main building blocks in a React application, and you will see them used throughout this book. |
I use the excellent Bootstrap CSS framework to style the HTML presented by the examples in this book. I describe the basic use of Bootstrap in Chapter 3, but to get started in this chapter, run the commands shown in Listing 1-7 to navigate to the todo folder and add the Bootstrap package to the project.
The command used to manage the packages in a project is npm, which is confusingly similar to npx, which is used only when creating a new project. It is important not to confuse the two commands.
As I explain in Chapter 4, the import statement is used to declare a dependency so that it becomes part of the application. The import keyword is most often used to declare dependencies on JavaScript code, but it can also be used for CSS stylesheets.

Running the example application
The App.js file contains a React component, which is named App. Components are the main building block for React applications, and they are written using JSX, which is a superset of JavaScript that allows HTML to be included in code files without requiring any special quoting. I describe JSX in more detail in Chapter 3, but in this listing, the App component defines a render method that React calls to get the content to display to the user.
React supports recent additions to the JavaScript language, such as the class keyword, which is used in Listing 1-10. I provide a primer for the most useful JavaScript features in Chapter 4.

Replacing the placeholder content
In regular HTML, the class attribute is used to assign elements to classes, which is how elements are styled when using the Bootstrap CSS framework. Even though it might not appear so, JSX files are JavaScript files, and JavaScript configures classes through the className property. The differences between pure HTML and JSX can be jarring when you first begin React development, but they soon will become second nature.
I provide a brief overview of working with the Bootstrap CSS framework in Chapter 3, where I explain the meaning of the classes to which the h4 element has been assigned in Listing 1-10, such as bg-primary, text-white, and p-2. You can ignore these classes for the moment, however, and just focus on the basic structure of the application.
React will write a warning message to the browser’s JavaScript console if you forget you are working with JSX and use standard HTML instead. If you use the class attribute instead of className, for example, you will see the Invalid DOM property 'class'. Did you mean 'className'? warning. To see the browser’s JavaScript console, press the F12 key and select the Console or JavaScript Console tab.
The constructor is a special method that is invoked when the component is initialized, and calling the super method within the constructor is required to ensure that the component is set up properly, as I explain in Chapter 11. The props parameter defined by the constructor is important in React development because it allows one component to configure another, which you will see shortly.
The term props is short for properties, and it reflects the way React creates the HTML content that is displayed in the browser, as I explain in Chapter 3.

Using state data and expressions in the App.js file in the src Folder

Changing the username
As I explain in Chapter 4, fat arrow functions are used to simplify responding to events, but they be used more widely and help keep the mix of HTML and JavaScript readable in a React application. The changeStateData method uses the setState method to set a new value for the userName property. When the setState method is called, React updates the component’s state data with the new values and then invokes the render method so that the expressions will generate updated content. This is why clicking the button changes the name shown in the browser window from Adam to Bob. I didn’t have to explicitly tell React that the value used by the expression changed—I just called the setState method to set the new value and left React to update the content in the browser.
The this keyword is required whenever you use the properties and methods defined by a component, including the setState method. Forgetting to use this is a common error in React development, and it is the first thing to check if you don’t get the behavior you expect.
I use both styles to define functions and methods in this book. For the most part, you can choose between conventional JavaScript functions and fat arrow functions, although there are some important considerations explained in Chapter 12.
This expression filters the objects in the todoItems state data array so that only incomplete items are selected and then reads the value of the length property, which is the value that the binding will display to the user. The JSX format makes it easy to mix HTML elements and code like this, although complex expressions can be difficult to read and are often defined in a property or method to keep the HTML as simple as possible.
The value prop is used to set the contents of the input element. In this case, the expression that the value prop contains will return the value of the newItemText state data property, which means that any change to the state data property will update the contents of the input element. The onChange prop tells React what to do when the change event is triggered, which will happen when the user types into the input element. This expression tells React to invoke the component’s updateNewTextValue method, which uses the setState method to update the newItemText state data property. This may seem like a circular approach, but it ensures that React knows how to deal with changes performed by code and by the user.
The spread operator is three periods, and it expands an array. The tools used for React development allow recent JavaScript features to be used and translates them into compatible code that can be understood by older web browsers. I describe the spread operator and other useful JavaScript features in Chapter 4.

Adding a new task
Each item in the array is mapped to a tr element, which is the HTML element for a table row. Within the tr element is a set of td elements that define HTML table cells. The HTML content produced by the map method contains further JavaScript expressions that populate the td elements with state data values or functions that will be invoked to handle an event.
As you will learn in detail in Chapter 13, React invokes a component’s render method when there is a change and compares the result with the HTML that is displayed in the browser so that only the differences are applied. React requires the key prop so that it can correlate the content is displayed with the data that produced it and manage changes efficiently.
The result of the changes in Listing 1-15 is that each to-do item is displayed with a checkbox that the user toggles to indicate that the task is complete. Each table row generated by the todoTableRows method contains an input element configured as a checkbox.
At the moment, all of the example application’s functionality is contained in a single component, which can become difficult to manage as new features are added. To help keep components manageable, functionality is delegated up into separate components that are responsible for specific features. These are known as child components, while the component that delegated the functionality is known as the parent.
When React invokes the TodoBanner component’s render method, the value of the name prop provided by the parent component will be included in the result. The other expression in the TodoBanner component’s render method uses the JavaScript filter method to select the incomplete items and determine how many there are, showing that props can be used in expressions that do more than just display their value.
This component will be responsible for displaying a single row in the table, showing details of a to-do item. The data that is received by a child component through its props is read-only and must not be altered. To make changes, parent components can use function props to provide children with callback functions that are invoked when something important happens. This combination allows collaboration between components: data props allow a parent to provide data to a child, and function props allow a child to communicate with this parent.
Child components can have their own state data, which is what this component uses to handle the content of its input element. The component invokes a function prop to notify its parent when the user clicks the Add button.
The expressions used to set the prop values provide a child component with access to specific data and methods defined by its parent. In this case, the name and tasks props are used to provide the TodoBanner component with the values of the userName and todoItems state data properties.
The basic features of the application are in place, and the set of components that provide those features are all working together. In this section, I add some finishing touches to complete the to-do application.
Using props to receive data and callback functions from a parent makes it easy to add new features to an application. The component defined in Listing 1-20 is a general-purpose feature that has no knowledge of the content that it is being used to manage, and it works entirely through its props: the description prop provides the label text it displays, the isChecked prop provides the initial state for the checkbox, and the callback prop provides the function that is invoked when the user toggles the checkbox and triggers the change event.
The VisibilityControl component is configured so it changes the value of the App component’s state data property named showCompleted when the user toggles the checkbox. To separate the complete and incomplete tasks, I added a parameter to the todoTableRows method and used the filter method to select objects from the state data array based on the value of the done property.
When the expression is evaluated, the table element will be included in the component’s content only if the showCompleted property is true. This is another example of how JSX mixes content and code. For the most part, JSX does a good job at blending elements and code statements, but it doesn’t excel at everything, and the syntax required for conditional statements is awkward, as this example shows.

Changing the task display
The final change is to store the data so that the user’s list is preserved when navigating away from the application. Later in the book, I demonstrate different ways of working with data stored on a server, but for this chapter I am going to keep the application simple and ask the browser to store the data using the Local Storage API, as shown in Listing 1-22.
The Local Storage API is a standard browser feature and isn’t specific to React development. See https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage for a good description of how local storage works.
The Local Storage API is accessed through the localStorage object, and the component uses the setItem method to store the to-do items when a new to-do item is created. The local storage feature is only able to store string values, so I serialize the data objects as JSON before they can be stored. The setState method can accept a function that will be updated once the state data has been updated, as described in Chapter 11, and that ensures that the most recent data is stored.
Components have a well-defined lifecycle, which is described in Chapter 13, and can implement methods to receive notifications about important events. The component in the listing implements the componentDidMount method, which is invoked early in the component’s life and provides a good opportunity to perform tasks such as loading data.
To retrieve the stored data, I have used the Local Storage API’s getItem method. I use the setState method to update the component with the stored data or with some default data if there is no stored data available.

Storing data
In this chapter, I created a simple example application to introduce you to the React development process and to demonstrate some important React concepts. You saw that React development is focused on components, which are defined in JSX files that combine JavaScript code and HTML content. When you create a project, everything that is required to work with JSX files, build the application, and deliver it to the browser for testing is included so that you can get started quickly and easily.
You also learned that React applications can contain multiple components, each of which is responsible for a specific feature and which receive the data and callback functions they require using props.
Many more React features are available, as you can tell from the size of this book, but the basic application I created in this chapter has shown you the most essential characteristics of React development and will provide a foundation for later chapters. In the next chapter, I put React in context and describe the structure and content of this book.
React is a flexible and powerful open-source framework for developing client-side applications; it takes cues from the world of server-side development and applies them to HTML elements, and it creates a foundation that makes building rich web applications easier. In this book, I explain how React works and demonstrate the different features it provides.
The React team makes frequent releases, which means there is an ongoing stream of fixes and features. Minor releases tend not to break existing features and largely contain bug fixes. The major releases can contain substantial changes and may not offer backward compatibility.
It doesn’t seem fair or reasonable to ask readers to buy a new edition of this book every few months, especially since the majority of React features are unlikely to change even in a major release. Instead, I am going to post updates following the major releases to the GitHub repository for this book, https://github.com/Apress/pro-react-16 .
This is an ongoing experiment for me (and for Apress), and I don’t yet know what form those updates may take—not least because I don’t know what the major releases of React will contain—but the goal is to extend the life of this book by supplementing the examples it contains.
I am not making any promises about what the updates will be like, what form they will take, or how long I will produce them before folding them into a new edition of this book. Please keep an open mind and check the repository for this book when new React versions are released. If you have ideas about how the updates could be improved, then e-mail me at adam@adam-freeman.com and let me know.
React isn’t the solution to every problem, and it is important to know when you should use React and when you should seek an alternative. React delivers the kind of functionality that used to be available only to server-side developers but is delivered entirely in the browser. The browser has to do a lot of work each time an HTML document to which React has been applied is loaded: data has to be loaded, components have to be created and composed, expressions have to be evaluated, and so on, creating the foundation for the features that I described in Chapter 1 and those that I explain throughout the rest of this book.
This kind of work takes time to perform, and the amount of time depends on the complexity of the React application and—critically—on the quality of the browser and the processing capability of the device. You won’t notice any performance issues when using the latest browsers on a capable desktop machine, but old browsers on underpowered smartphones can really slow down the initial setup of a React application.
The goal, therefore, is to perform this setup as infrequently as possible and deliver as much of the app as possible to the user when it is performed. This means giving careful thought to the kind of web application you build. In broad terms, there are two basic kinds of web application: round-trip and single-page.
For a long time, web apps were developed to follow a round-trip model. The browser requests an initial HTML document from the server. User interactions—such as clicking a link or submitting a form—leads the browser to request and receive a completely new HTML document. In this kind of application, the browser is essentially a rending engine for HTML content, and all of the application logic and data resides on the server. The browser makes a series of stateless HTTP requests that the server handles by generating HTML documents dynamically.
A lot of current web development is still for round-trip applications, especially for line-of-business projects, not least because they put few demands on the browser and have the widest possible client support. But there are some serious drawbacks to round-trip applications: they make the user wait while the next HTML document is requested and loaded, they require a large server-side infrastructure to process all the requests and manage all the application state, and they can require more bandwidth because each HTML document has to be self-contained, which can lead to the same content being included in each response from the server. React is not well-suited to round-trip applications because the browser has to perform the initial setup process for each new HTML document that is received from the server.
Single-page applications (SPAs) take a different approach. An initial HTML document is sent to the browser, but user interactions lead to HTTP requests for small fragments of HTML or data inserted into the existing set of elements being displayed to the user. The initial HTML document is never reloaded or replaced, and the user can continue to interact with the existing HTML while the HTTP requests are being performed asynchronously, even if that just means seeing a “data loading” message.
React is well-suited to single-page applications because the work that the browser has to perform to initialize the application has to be performed only once, after which the application runs in the browser, responding to user interaction and requesting the data or content that is required in the background.
There are two main competitors to React: Angular and Vue.js. There are differences between them, but, for the most part, all of these frameworks are excellent, all of them work in similar ways, and all of them can be used to create rich and fluid client-side applications.
The real difference between these frameworks is the developer experience. Angular requires you to use TypeScript to be effective, for example, whereas it is just an option with React and Vue.js projects. React and Vue.js mix HTML and JavaScript together in a single file, which not everyone likes, although the way this is done differs for each framework.
My advice is simple: pick the framework that you like the look of the most and switch to one of the others if you don’t get on with it. That may seem like an unscientific approach, but there isn’t a bad choice to make, and you will find that many of the core concepts carry over between frameworks even if you change the one you use.
The type of application isn’t the only consideration when deciding whether React would be well-suited to a project. The complexity of a project is also important, and I often from readers who have embarked on a project using a client-side framework such as React, Angular, or Vue.js, when something much simpler would have been sufficient. A framework such as React requires a substantial time commitment to master (as the size of this book illustrates), and this effort isn’t justified if you just need to validate a form or populate a select element programmatically.
In the excitement that surrounds client-side frameworks, it is easy to forget that browsers provide a rich set of APIs that can be used directly and that these are the same APIs that React relies on for all of its features. If you have a problem that is simple and self-contained, then you should consider using the browser APIs directly, starting with the Document Object Model (DOM) API. You will see that some of the examples in this book use the browser APIs directly, but a good place to start if you are new to browser development is https://developer.mozilla.org , which contains good documentation for all of the APIs that browsers support.
The drawback of the browser APIs, especially the DOM API, is that they can be awkward to work with and older browsers tend to implement features differently. A good alternative to working directly with the browser APIs, especially if you have to support older browsers, is jQuery ( https://jquery.org ). jQuery simplifies working with HTML elements and has excellent support for handling events, animations, and asynchronous HTTP requests.
React comes into its own in large applications, where there are complex workflows to implement, different types of users to deal with, and substantial volumes of data to be processed. In these situations, you can work directly with the browser APIs, but it becomes difficult to manage the code and hard to scale up the application. The features provided by React make it easier to build large and complex applications and to do so without getting bogged down in reams of unreadable code, which is often the fate of complex projects that don’t adopt a framework.
If you decide that React is the right choice for your project, then you should be familiar with the basics of web development, have an understanding of how HTML and CSS work, and have a working knowledge of JavaScript. If you are a little hazy on some of these details, I provide primers for the features I use in this book in Chapters 3 and 4. https://developer.mozilla.org is a good place to brush up on the fundamentals of HTML, CSS, and JavaScript.
The only development tools needed for React development are the ones you installed in Chapter 1 when you created your first application. Some later chapters require additional packages, but full instructions are provided. If you successfully built the application in Chapter 1, then you are set for React development and for the rest of the chapters in this book.
This book is split into three parts, each of which covers a set of related topics.
Part 1 of this book provides the information you need to get started with React development. It includes this chapter and primer/refresher chapters for the key technologies used in React development, including HTML, CSS, and JavaScript. Chapter 1 showed you how to create a simple React application, and Chapters 5–8 take you through the process of building a more realistic application, called SportsStore.
Part 2 of this book covers the core React features that are required in most projects. React provides a lot of built-in functionality, which I describe in depth, along with the way that custom code and content is added to a project to create bespoke features.
React relies on additional packages to provide the advanced features that are required by most complex applications. In Part 3 of this book, I introduce the most important of these packages, show you how they work, and explain how they add to the core React features.
This is a listing from Chapter 11, which shows the contents of a file called SimpleButton.js that can be found in the src folder. Don’t worry about the content of the listing or the purpose of the file; just be aware that this type of listing contains the complete contents of a file and that the changes you need to make to follow the example are shown in bold.
This is a later listing from Chapter 11, and it shows a set of changes that are applied to only one part of a much larger file. When you see a partial listing, you will know that the rest of the file does not have to change and that only the sections marked in bold are different.
The changes are still marked in bold, and the parts of the file that are omitted from the listing are not affected by this example.
You can download the example projects for all the chapters in this book from https://github.com/Apress/pro-react-16 . The download is available without charge and contains everything that you need to follow the examples without having to type in all of the code.
You can find errata for this book at https://github.com/Apress/pro-react-16 .
If you have problems making the examples in this chapter work or if you find a problem in the book, then you can e-mail me at adam@adam-freeman.com, and I will try my best to help. Please check the errata for this book to see whether it contains a solution to your problem before contacting me.
In this chapter, I explained when React is a good choice for projects and outlined the alternatives and competitors. I also outlined the content and structure of this book, explained where to get updates, and explained how to contact me if you have problems with the examples in this book. In the next chapter, I provide a primer for the HTML and CSS features that I use in this book to explain React development.
In this chapter, I provide a brief overview of HTML and explain how HTML content can be mixed with JavaScript code when using JSX, which is the superset of JavaScript supported by the React development tools that allows HTML to be mixed with code. I also introduce the Bootstrap CSS framework, which I use to style the content in the examples throughout this book.
Don’t worry if not all the features described in this chapter make immediate sense. Some rely on recent additions to the JavaScript language that you may not have encountered before, which are described in Chapter 4 or explained in detail in other chapters.
To create the project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 3-1.
You can download the example project for this chapter—and for all of the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Once the project has been created, run the commands shown in Listing 3-2 to navigate to the project folder and install the Bootstrap CSS framework.
When you create a new project, you may see warnings about security vulnerabilities. React development relies on a large number of packages, each of which has its own dependencies, and security issues will inevitably be discovered. For the examples in this book, it is important to use the package versions specified to ensure you get the expected results. For your own projects, you should review the warnings and update to versions that resolve the problems.

Running the example application
At the heart of all React web applications are HTML elements, which are used to describe the content that will be presented to the user. In a React application, the contents of the static index.html file in the public folder are combined with the HTML elements created dynamically by React to produce an HTML document that the browser displays to the user.

The anatomy of an HTML element
The name of this element (also referred to as the tag name or just the tag) is h4, and it tells the browser that the content between the tags should be treated as a header. There are a range of header elements, ranging from h1 to h6, where h1 is conventionally used for the most important content, h2 for slightly less important content, and so on.
When you define an HTML element, you start by placing the tag name in angle brackets (the < and > characters) and end an element by using the tag in a similar way, except that you also add a / character after the left-angle bracket (<), to create the start tag and end tag.
Element | Description |
|---|---|
a | A link (more formally known as an anchor), which the user clicks to navigate to a new URL or a new location within the current document |
button | A button, which can be clicked by the user to initiate an action |
div | A generic element; often used to add structure to a document for presentation purposes |
h1 to h6 | A header |
input | A field used to gather a single data item from the user |
table | A table, used to organize content into rows and columns |
tbody | The body of the table (as opposed to the header or footer) |
td | A content cell in a table row |
th | A header cell in a table row |
thead | The header of a table |
tr | A row in a table |

Adding parent and child elements
Some elements have restrictions on the types of elements that can be their children. The div elements in the example can contain any other element and are used to add structure to an HTML document, often so that content can be easily styled. Other elements have more specific roles that require specific types of elements to be used as children. For example, a tbody element, which you will see in later chapters and which represents the body of a table, can contain only one or more tr elements, each of which represents a table row.
Don’t worry about learning all of the HTML elements and their relationships. You will pick up everything you need to know as you follow the examples in later chapters, and most code editors will display a warning if you try to create invalid HTML.
A void element is defined in a single tag, and you add a / character before the last angle bracket (the > character). The element shown here is the most common example of a void element, and it is used to gather data from the user in HTML forms. You will see many examples of void elements in later chapters.

The name and value of an attribute
The name of this attribute is class, which is used to group related elements, typically so that their appearance can be managed consistently. This is why the class attribute has been used in this example, and the attribute value associates the h4 element with a number of classes that relate to styles provided by the Bootstrap CSS package, which I describe later in the chapter.

Creating an element using the DOM API
Most of the properties defined by element objects have the same name as the attributes they correspond to. There are some exceptions, including className, which is used because the class keyword is reserved in many programming languages, including JavaScript.
It is worth emphasizing that the index.html file does not contain this HTML element. Instead, it contains a series of JavaScript statements that instructed the browser to create the element and add it to the content presented to the user.
React uses the DOM API to create the HTML elements specified by the render method, which it does by creating an object that is configured through its properties. The JSX format used for React development allows HTML elements to be defined declaratively, but the result is still JavaScript when the file is processed by the development tools, which is why the h4 element is configured using className and not class in the App render method. JSX lets elements appear to be configured using attributes, but they are just the means by which values are specified for properties, and this is why the term prop is used so much in React development.
No special steps are required to use JSX, which is supported by the tools added to the project by the create-react-app package. I explain how elements defined using JSX are transformed into JavaScript in Chapter 9.

Using an expression to set the content of an element

Mixing an expression and static content

Performing computation in an expression
When you use a function in an expression, you must invoke it with parentheses (the ( and ) characters), as shown in the listing, so that the result of the function is included in the content generated by the component.
The expression in this example invokes the isEven method, using the count value as the argument. The result is the same as the previous listing.
The result is the same as the previous listing.

Handling an event
HTML elements tell the browser what kind of content they represent, but they don’t provide any information about how that content should be displayed. The information about how to display elements is provided using Cascading Style Sheets (CSS). CSS consists of a comprehensive set of properties that can be used to configure every aspect of an element’s appearance and a set of selectors that allow those properties to be applied.
One of the main problems with CSS is that some browsers interpret properties slightly differently, which can lead to variations in the way that HTML content is displayed on different devices. It can be difficult to track down and correct these problems, and CSS frameworks have emerged to help web app developers style their HTML content in a simple and consistent way.
The most popular CSS framework is Bootstrap, which was originally developed at Twitter but has become a widely used open source project. Bootstrap consists of a set of CSS classes that can be applied to elements to style them consistently and some optional JavaScript code that performs additional enhancement (but that I do not use in this book). I use Bootstrap in my own projects; it works well across browsers, and it is simple to use. I use the Bootstrap CSS styles in this book because they let me style my examples without having to define and then list my own custom CSS in each chapter. Bootstrap provides a lot more features than the ones I use in this book; see http://getbootstrap.com for full details.
I don’t want to get into too much detail about Bootstrap because it isn’t the topic of this book, but I do want to give you enough information so you can tell which parts of an example are React features and which are related to Bootstrap.
Name | Description |
|---|---|
bg-primary | This class applies a style context to provide a visual cue about the purpose of the element. See the “Using Contextual Classes” section. |
text-white | This class applies a style that sets the text color for the element’s content to white. |
text-center | This class applies a style that horizontally centers the element’s content. |
p-2 | This class applies a style that adds spacing around the element’s content, as described in the “Using Margin and Padding” section. |
m-1 | This class applies a style that adds spacing around the element, as described in the “Using Margin and Padding” section. |
Name | Description |
|---|---|
primary | Indicates the main action or area of content |
secondary | Indicates the supporting areas of content |
success | Indicates a successful outcome |
info | Presents additional information |
warning | Presents warnings |
danger | Presents serious warnings |
muted | De-emphasizes content |
dark | Increases contrast by using a dark color |
white | Increases contrast by using white |
Bootstrap provides classes that allow the style contexts to be applied to different types of elements. The h4 element with which I started this section has been added to the bg-primary class, which sets the background color of an element to indicate that it is related to the main purpose of the application. Other classes are specific to a certain set of elements, such as btn-primary, which is used to configure button and a elements so they appear as buttons whose colors are consistent with other elements in the primary context. Some of these context classes must be applied in conjunction with other classes that configure the basic style of an element, such as the btn class, which is combined with the btn-primary class.
Bootstrap includes a set of utility classes that are used to add padding, which is space between an element’s edge and its content, and margin, which is space between an element’s edge and the surrounding elements. The benefit of using these classes is that they apply a consistent amount of spacing throughout the application.
The classes that apply margin and padding to elements follow a well-defined naming schema: first, the letter m (for margin) or p (for padding), followed by an optional letter selecting specific edges (t for top, b for bottom, l for left, or r for right), then a hyphen, and, finally, a number indicating how much space should be applied (0 for no spacing, or 1, 2, 3, 4 or 5 for increasing amounts). If there is no letter to specify edges, then the margin or padding will be applied to all edges. To help put this schema in context, the p-2 class to which the h4 element has been added applies padding level 2 to all of the element’s edges.
The Bootstrap grid layout system is simple to use. A top-level div element is assigned to the container class (or the container-fluid class if you want it to span the available space). You specify a column by applying the row class to a div element, which has the effect of setting up the grid layout for the content that the div element contains.

Using a grid layout
Name | Description |
|---|---|
table | Applies general styling to a table element and its rows |
table-striped | Applies alternate-row striping to the rows in the table body |
table-bordered | Applies borders to all rows and columns |
table-sm | Reduces the spacing in the table to create a more compact layout |
Notice that I have used the thead element when defining the tables in Listing 3-19. Browsers will automatically add any tr elements that are direct descendants of table elements to a tbody element if one has not been used. You will get odd results if you rely on this behavior when working with Bootstrap, and it is always a good idea to use the full set of elements when defining a table.

Styling a table

Styling form elements
In this chapter, I provided a brief overview of HTML and explained how it can be mixed with JavaScript code in React development, albeit with some changes and restrictions. I also introduced the Bootstrap CSS framework, which I use throughout this book but which is not directly related to React. You need to have a good grasp of HTML and CSS to be truly effective in web application development, but the best way to learn is by firsthand experience, and the descriptions and examples in this chapter will be enough to get you started and provide just enough background information for the examples ahead. In the next chapter, I continue the primer theme and introduce the most important JavaScript features used in this book.
In this chapter, I provide a quick tour of the most important features of the JavaScript language as they apply to React development. I don’t have the space to describe JavaScript completely, so I have focused on the essentials that you’ll need to get up to speed and follow the examples in this book.
Problem | Solution | Listing |
|---|---|---|
Provide instructions that will be executed by the browser | Use JavaScript statement | 4 |
Delay execution of statements until they are required | Use JavaScript functions | 5–7, 10–12 |
Define functions with variable numbers of parameters | Use default and rest parameters | 8, 9 |
Express functions concisely | Use fat arrow functions | 13 |
Define variables and constants | Use the let and const keywords | 14, 15 |
Use the JavaScript primitive types | Use the string, number, or boolean keywords | 16, 17, 19 |
Define strings that include other values | Use template strings | 18 |
Execute statements conditionally | Use the if and else and switch keywords | 20 |
Compare values and identities | Use the equality and identity operators | 21, 22 |
Convert types | Use the type conversion keywords | 23–25 |
Group related items | Define an array | 26, 27 |
Read or change a value in an array | Use the index accessor notation | 28, 29 |
Enumerate the contents of an array | Use a for loop or the forEach method | 30 |
Expand the contents of an array | Use the spread operator | 31, 32 |
Process the contents of an array | Use the built-in array method | 33 |
Gather related values into a single unit | Define an object using a literal or a class | 34–36, 40 |
Define an operation that can be performed on the values of an object | Define a method | 37, 39, 43, 44 |
Copy properties and value from one object to another | Use the Object.assign method or use the spread operator | 41, 42 |
Group related features | Define a JavaScript module | 45–54 |
Observe an asynchronous operation | Define a Promise and use the async and await keywords | 55–58 |
In this chapter, I continue working with the primer project created in Chapter 3. To prepare for this chapter, I added a file called example.js to the src folder and added the code shown in Listing 4-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application

A result in the browser’s console
Defining a function simple: use the const keyword followed by the name you want to give the function, followed by the equal sign (=) and the function keyword, followed by parentheses (the ( and ) characters). The statements you want the function to contain are enclosed between braces (the { and } characters).
You can see that the statement inside the function isn’t executed immediately, but other than demonstrating how functions are defined, this example isn’t especially useful because the function is invoked immediately after it has been defined. Functions are much more useful when they are invoked in response to some kind of change or event, such as user interaction.
The code works in the same way as Listing 4-5 but is more familiar for most developers. This example produces the same result as Listing 4-5.
The number of arguments you provide when you invoke a function doesn’t need to match the number of parameters in the function. If you call the function with fewer arguments than it has parameters, then the value of any parameters you have not supplied values for is undefined, which is a special JavaScript value. If you call the function with more arguments than there are parameters, then the additional arguments are ignored.
The consequence of this is that you can’t create two functions with the same name and different parameters and expect JavaScript to differentiate between them based on the arguments you provide when invoking the function. This is called polymorphism, and although it is supported in languages such as Java and C#, it isn’t available in JavaScript. Instead, if you define two functions with the same name, then the second definition replaces the first.
These functions perform the same work as the ones in Listing 4-12. There are three parts to an arrow function: the input parameters, then an equal sign and a greater-than sign (the “arrow”), and finally the function result. The return keyword and curly braces are required only if the arrow function needs to execute more than one statement. There are more examples of arrow functions later in this chapter, and you will see them used throughout the book.
In React development, you can decide which style of function you prefer to use, and you will see that I use both in the examples in this book. Care must be taken when defining functions that respond to events, however, as explained in Chapter 12.
The let keyword is used to declare variables and, optionally, assign a value to the variable in a single statement—as opposed to the const keyword I used in earlier examples, which creates a constant value that cannot be modified.
This may seem like an odd example, but there is another keyword that can be used to declare variables: var. The let and const keywords are relatively new additions to the JavaScript specification that is intended to address some oddities in the way var behaves. Listing 4-15 takes the example from Listing 4-14 and replaces let with var.
It is good practice to use the const keyword for any value that you don’t expect to change so that you receive an error if any modifications are attempted. This is a practice that I rarely follow, however—in part because I am still struggling to adapt to not using the var keyword and in part because I write code in a range of languages and there are some features that I avoid because they trip me up when I switch from one to another. If you are new to JavaScript, then I recommend trying to use const and let correctly and avoiding following my poor behavior.
Some browsers will show repeated statements as a single line with a number next to them indicating how many times that output has occurred. This means you may see one statement with the number 2 next to it, indicating that it occurred twice.
These messages can be cryptic until you get used to them, and the easiest way to learn more about them is to consult the documentation for the ESLint package, which applies a set of rules to JavaScript code and is used by the React development tools to create the warnings. The name of the rule is included in the warning, and the name of the rule that produced the warnings for Listing 4-15 is no-redeclare, which is described at https://eslint.org/docs/rules/no-redeclare .
The inner function in this example is able to access the local variables of the outer function, including its parameter. This is a powerful feature that means you don’t have to define parameters on inner functions to pass around data values, but caution is required because it is easy to get unexpected results when using common variable names like counter or index, where you may not realize that you are reusing a variable name from the outer function.
JavaScript defines a basic set of primitive types: string, number, boolean. This may seem like a short list, but JavaScript manages to fit a lot of flexibility into these types.
I am simplifying here. There are three other primitives that you may encounter. Variables that have been declared but not assigned a value are undefined, while the null value is used to indicate that a variable has no value, just as in other languages. The final primitive type is Symbol, which is an immutable value that represents a unique ID but which is not widely used at the time of writing.
Name | Description |
|---|---|
length | This property returns the number of characters in the string. |
charAt(index) | This method returns a string containing the character at the specified index. |
concat(string) | This method returns a new string that concatenates the string on which the method is called and the string provided as an argument. |
indexOf(term, start) | This method returns the first index at which term appears in the string or -1 if there is no match. The optional start argument specifies the start index for the search. |
replace(term, newTerm) | This method returns a new string in which all instances of term are replaced with newTerm. |
slice(start, end) | This method returns a substring containing the characters between the start and end indices. |
split(term) | This method splits up a string into an array of values that were separated by term. |
toUpperCase() toLowerCase() | These methods return new strings in which all the characters are uppercase or lowercase. |
trim() | This method returns a new string from which all the leading and trailing whitespace characters have been removed. |
You don’t have to specify which kind of number you are using. You just express the value you require, and JavaScript will act accordingly. In the listing, I have defined an integer value, defined a floating-point value, and prefixed a value with 0x to denote a hexadecimal value.
Operator | Description |
|---|---|
++, -- | Pre- or post-increment and decrement |
+, -, *, /, % | Addition, subtraction, multiplication, division, remainder |
<, <=, >, >= | Less than, less than or equal to, more than, more than or equal to |
==, != | Equality and inequality tests |
===, !== | Identity and nonidentity tests |
&&, || | Logical AND and OR (|| is used to coalesce null values) |
= | Assignment |
+ | String concatenation |
?: | Three-operand conditional statement |
The second result is the kind that causes confusion. What might be intended to be an addition operation is interpreted as string concatenation through a combination of operator precedence and over-eager type conversion. To avoid this, you can explicitly convert the types of values to ensure you perform the right kind of operation, as described in the following sections.
Method | Description |
|---|---|
toString() | This method returns a string that represents a number in base 10. |
toString(2) toString(8) toString(16) | This method returns a string that represents a number in binary, octal, or hexadecimal notation. |
toFixed(n) | This method returns a string representing a real number with n digits after the decimal point. |
toExponential(n) | This method returns a string that represents a number using exponential notation with one digit before the decimal point and n digits after. |
toPrecision(n) | This method returns a string that represents a number with n significant digits, using exponential notation if required. |
Method | Description |
|---|---|
Number(str) | This method parses the specified string to create an integer or real value. |
parseInt(str) | This method parses the specified string to create an integer value. |
parseFloat(str) | This method parses the specified string to create an integer or real value. |
I have created a new array by calling new Array(). This creates an empty array, which I assign to the variable myArray. In the subsequent statements, I assign values to various index positions in the array. (There is no output from this listing.)
There are a couple of things to note in this example. First, I didn’t need to declare the number of items in the array when I created it. JavaScript arrays will resize themselves to hold any number of items. The second point is that I didn’t have to declare the data types that the array will hold. Any JavaScript array can hold any mix of data types. In the example, I have assigned three items to the array: a number, a string, and a boolean.
In this example, I specified that the myArray variable should be assigned a new array by specifying the items I wanted in the array between square brackets ([ and ]). (There is no console output from this listing, although there will be a warning because the array is defined but not used.)
The JavaScript for loop works just the same way as loops in many other languages. You determine how many elements there are in the array by using the length property.
Arrays can also be de-structured, whereby the individual elements of an array are assigned to different variables, so that [var1, var2] = [3, 4] assigns a value of 3 to var1 and 4 to var2. Array de-structuring is used by the hooks feature, which is described in Chapter 11.
Method | Description |
|---|---|
concat(otherArray) | This method returns a new array that concatenates the array on which it has been called with the array specified as the argument. Multiple arrays can be specified. |
join(separator) | This method joins all the elements in the array to form a string. The argument specifies the character used to delimit the items. |
pop() | This method removes and returns the last item in the array. |
shift() | This method removes and returns the first element in the array. |
push(item) | This method appends the specified item to the end of the array. |
unshift(item) | This method inserts a new item at the start of the array. |
reverse() | This method returns a new array that contains the items in reverse order. |
slice(start,end) | This method returns a section of the array. |
sort() | This method sorts the array. An optional comparison function can be used to perform custom comparisons. |
splice(index, count) | This method removes count items from the array, starting at the specified index. The removed items are returned as the result of the method. |
unshift(item) | This method inserts a new item at the start of the array. |
every(test) | This method calls the test function for each item in the array and returns true if the function returns true for all of them and false otherwise. |
some(test) | This method returns true if calling the test function for each item in the array returns true at least once. |
filter(test) | This method returns a new array containing the items for which the test function returns true. |
find(test) | This method returns the first item in the array for which the test function returns true. |
findIndex(test) | This method returns the index of the first item in the array for which the test function returns true. |
forEach(callback) | This method invokes the callback function for each item in the array, as described in the previous section. |
includes(value) | This method returns true if the array contains the specified value. |
map(callback) | This method returns a new array containing the result of invoking the callback function for every item in the array. |
reduce(callback) | This method returns the accumulated value produced by invoking the callback function for every item in the array. |
If you are returning an object literal as the result from a fat arrow function, then you must enclose the object in parentheses, e.g., myFunc = () => ({ data: "hello"}). You will receive an error if you omit the parentheses because the build tools will assume that the curly braces of the object literal are the start and end of a function body.
Classes are defined using the class keyword. The constructor is a special method that is automatically invoked when an object is created from the class, which is known as instantiating the class. An object created from a class is said to be an instance of that class.
In JavaScript, the constructor is used to define the properties that instances will have, and the current object is referred to using the this keyword. The constructor in Listing 4-40 defines name and weather properties by assigning values to this.name and this.weather. Classes define methods by assigning functions to names, and in Listing 4-40, the class defines a printMessages method that is defined using the fat arrow syntax and that prints out messages to the console. Notice that the this keyword is required to access the values of the name and weather variables.
There are other ways to use JavaScript classes, but I have focused on the way they are used in React development and in the examples throughout this book. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes for full details.
React applications are too complex to define in a single JavaScript file. To break up an application into more manageable chunks, JavaScript supports modules, which contain JavaScript code that other parts of the application depend on. In the sections that follow, I explain the different ways that modules can be defined and used.
The sum.js file contains a function that accepts an array of values and uses the JavaScript array reduce method to sum them and return the result. What’s important about this example is not what it does but the fact that the function is defined in its own file, which is the basic building block for a module.
There are two keywords used in Listing 4-45 that you will often encounter when defining modules: export and default. The export keyword is used to denote the features that will be available outside the module. By default, the contents of the JavaScript file are private and must be explicitly shared using the export keyword before they can be used in the rest of the application. The default keyword is used when the module contains a single feature, such as the function defined in Listing 4-45. Together, the export and default keywords are used to specify that the only function in the sum.js file is available for use in the rest of the application.

Declaring a dependency on a module
The import keyword is followed by an identifier, which is the name by which the function will be known when it is used, and the identifier in this example is additionFunction.
Notice that it is the import statement in which the identifier is applied, which means that the code that consumes the function from the module chooses the name by which it will be known and that multiple import statements for the same module in different parts of the application can use different names to refer to the same function. See the next section for details of how the module can specify the names of the features it contains.
The from keyword follows the identifier, which is then followed by the location of the module. It is important to pay close attention to the location because different behaviors are created by different location formats, as described in the sidebar.
This location tells the build tools that there is a dependency on the sum module, which can be found in the same folder as the file that contains the import statement. Notice that the file extension is not included in the location.
The location for this import statement doesn’t start with a period and will be interpreted as a dependency on the react module in the project’s node_modules folder, which is the package that provides the core React application features.
I used the as keyword to specify that the subtract function should be given the name deduct when imported into the example.js file. This listing produces the same output as Listing 4-53.
An asterisk is used to import everything in a module, followed by the as keyword and an identifier through which the module functions and values will be accessed. In this case, the identifier is ops, which means that the multiply, subtract, and divide functions can be accessed as ops.multiply, ops.subtract, and ops.divide. This listing produces the same output as Listing 4-53.
A promise is a background activity that will be completed at some point in the future. The most common use for promises in this book is requesting data using an HTTP request, which is performed asynchronously and produces a result when a response is received from the web server.
The browser executes the statements in the example.js file and invokes the asyncAdd function as instructed. The browser moves on to the next statement in the example.js file, which writes a message to the console using the result provided by asyncAdd—but this happens before the asynchronous task has been completed, which is why the output is undefined. The asynchronous task subsequently completes, but it is too late for the result to be used by the example.js file.
It can be difficult to unpack the functions in this example. The new keyword is used to create a Promise, which accepts the function that is to be observed. The observed function is provided with a callback that is invoked when the asynchronous task has completed and that accepts the result of the task as an argument. Invoking the callback function is known as resolving the promise.
JavaScript provides two keywords—async and await—that support asynchronous operations without having to work directly with promises. In Listing 4-59, I have applied these keywords in the example.js file.
It is important to understand that using async/await doesn’t change the way that an application behaves. The operation is still performed asynchronously, and the result will not be available until the operation completes. These keywords are just a convenience to simplify working with asynchronous code so that you don’t have to use the then method.
In this chapter, I provided a brief primer on JavaScript, focusing on the core functionality that will get you started for React development. In the next chapter, I start the process of building a more complex and realistic project, called SportsStore.
In Chapter 2, I built a quick and simple React application. Small and focused examples allow me to demonstrate specific features, but they can lack context. To help overcome this problem, I am going to create a simple but realistic e-commerce application.
My application, called SportsStore, will follow the classic approach taken by online stores everywhere. I will create an online product catalog that customers can browse by category and page, a shopping cart where users can add and remove products, and a checkout where customers can enter their details and place their orders. I will also create an administration area that includes create, read, update, and delete (CRUD) facilities for managing products and orders—and I will protect it so that only logged-in administrators can make changes. Finally, I show you how to prepare a React application for deployment.
My goal in this chapter and those that follow is to give you a sense of what real React development is like by creating as realistic an example as possible. I want to focus on React and the related packages that are used in most projects, of course, and so I have simplified the integration with external systems, such as the database, and omitted others entirely, such as payment processing.
The SportsStore example is one that I use in all of my books, not least because it demonstrates the ways in which different frameworks, languages, and development styles can be used to achieve the same result. You don’t need to have read any of my other books to follow this chapter, but you will find the contrasts interesting if you already own my Pro ASP.NET Core MVC 2 or Pro Angular 6 book, for example.
The React features that I use in the SportsStore application are covered in-depth in later chapters. Rather than duplicate everything here, I tell you just enough to make sense of the example application and refer you to other chapters for in-depth information. You can either read the SportsStore chapters from end to end to get a sense of how React works or jump to and from the detail chapters to get into the depth.
Either way, don’t expect to understand everything right away—React applications have a lot of moving parts and depend on a lot of packages, and the SportsStore application is intended to show you how they fit together without diving too deeply into the details that the rest of the book describes.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
The create-react-app tool will create a new React project named sportsstore with the packages, configuration files, and placeholder content required to start development. The project setup process may take some time to complete because there is a large number of NPM packages to download and install.
When you create a new project, you may see warnings about security vulnerabilities. React development relies on a large number of packages, each of which has its own dependencies, and security issues will inevitably be discovered. For the examples in this book, it is important to use the package versions specified to ensure you get the expected results. For your own projects, you should review the warnings and update to versions that resolve the problems.
Additional packages are required for the SportsStore project, in addition to the core React libraries and development tools installed by the create-react-app package. Run the commands shown in Listing 5-2 to navigate to the sportsstore folder and add the packages. (The npm install command can be used to add multiple packages in one go, but the result is a long command where it is easy to omit a package. To avoid errors, I add packages individually throughout this book.)
It is important to use the version numbers shown in the listing. You may see warnings about unmet peer dependencies as you add the packages, but these can be ignored.
Name | Description |
|---|---|
bootstrap | This package provides the CSS styles that I used to present HTML content throughout the book. |
fontawesome-free | This package provides icons that can be included in HTML content. I have used the free package, but there is a more comprehensive paid-for option available, too. |
redux | This package provides a data store, which simplifies the process of coordinating the different parts of the application. See Chapter 19 for details. |
react-redux | This package integrates a Redux data store into a React application, as described in Chapters 19 and 20. |
react-router-dom | This package provides URL routing, which allows the content presented to the user to be selected based on the browser’s current URL, as described in Chapters 21 and 22. |
axios | This package is used to make HTTP requests and will be used to access RESTful and GraphQL services, as described in Chapters 23–25. |
graphql | This package contains the reference implementation of the GraphQL specification. |
apollo-boost | This package contains a client used to consume a GraphQL service, as described in Chapter 25. |
react-apollo | This package is used to integrate the GraphQL client into a React application, as described in Chapter 25. |
Name | Description |
|---|---|
json-server | This package will be used to provide a RESTful web service in Chapter 6. |
jsonwebtoken | This package will be used to authenticate users in Chapter 8. |
graphql | This package will be used to define the schema for the GraphQL server in Chapter 7. |
express | This package will be used to host the back-end servers. |
express-graphql | This package will be used to create a GraphQL server. |
cors | This package is used to enable cross-origin request sharing (CORS) requests. |
faker | This package generates fake data for testing and is used in Chapter 6. |
chokidar | This package monitors files for changes. |
npm-run-all | This package is used to run multiple NPM scripts in a single command. |
connect-history-api-fallback | This package is used to respond to HTTP requests with the index.html file and is used in the production server in Chapter 8. |
The code in Listing 5-5 creates three data collections that will be used by the application. The products collection contains the products for sale to the customer, the categories collection contains the set of categories into which the products are organized, and the orders collection contains the orders that customers have placed (but is currently empty).
This change uses the npm-run-all package to run the React development server and the web service at the same time.

Running the example application
The starting point for SportsStore is the data store, which will be the repository for the data presented to the user and the supporting details required to coordinate application features, such as pagination.
Redux data stores separate reading data from the operations that change it. This can feel awkward at first, but it is similar to other parts of React development, such as component state data and using GraphQL, and it quickly becomes second nature.
There are two data types—PRODUCTS and CATEGORIES—and a single action, DATA_LOAD, which will populate the data store. There is no requirement to defined action types this way, but using constant values avoids typos when specifying action types elsewhere in the application.
The use of action creators is described in Chapter 19, but the only requirement for the objects produced by action creators is they must have a type property whose value specifies the type of change required to the data store. It is a good idea to use a common set of properties in action objects so that they can be handled consistently, and the action creator defined in Listing 5-11 returns an action object that has a payload property, which is the convention I will use for all of the SportsStore data store actions.
The payload property for the action object in Listing 5-11 has a dataType property that indicates the type of data that the action relates to and a data property that provides the data to be added to the data store. The value for the data property is obtained from the placeholder data at the moment, but I replace this with data obtained from a web service in Chapter 6.
Reducers are required to create and return new objects that incorporate any required changes. If the action type isn’t recognized, the reducer must return the data store object it received unchanged. The reducer in Listing 5-12 handles the DATA_LOAD action by creating a new object with all the properties of the old store plus the new data received in the action. Reducers are described in more detail in Chapter 19.
The Redux package provides the createStore function, which sets up a new data store using a reducer. This is enough to create a data store to get started with, but I will add additional features later so that further operations can be performed and so that data can be loaded from a web service.

The basic structure of the application
Name | Description |
|---|---|
/shop/products | This URL will display all of the products to the user, regardless of category. |
/shop/products/chess | This URL will display the products in a specific category. In this case, the URL will select the Chess category. |
I have adopted the British term shop for the part of the application that offers products for sale to customers. I want to avoid confusion between the data store, in which the application’s data is kept, and the product store, from which the user makes purchases.
Responding to the browser’s URL in the application is known as URL routing, which is provided by the React Router package added in Listing 5-2, and which is described in detail in Chapters 21 and 22.
Components are created to perform small tasks or display small amounts of content and are combined to create more complex features. The ProductList component defined in Listing 5-14 is responsible for displaying details of a list of products, whose details are received through a prop named product. Props are used to configure components and allow them to do their work—such as display details of a product—without getting involved in where the data comes from. The ProductList component generates HTML content that includes the value of each product’s name, price, and description properties, but it doesn’t have knowledge of how those products are defined in the application or whether they have been defined locally or retrieved from a remote server.
The selection of a category will be handled by navigating to a new URL, which is done using the Link component provided by the React Router package. When the user clicks a Link, the browser is asked to navigate to a new URL without sending any HTTP requests or reloading the application. The details included in the new URL, such as the selected category in this case, allow different parts of the application to work together.
The CategoryNavigation component receives the array of categories through a prop named categories. The component checks to ensure that the array has been defined and uses the map method to generate the content for each array item. React requires a key prop to be applied to the elements generated by the map method so that changes to the array can be handled efficiently, as explained in Chapter 10. The result is a Link component for each category that is received in the array with an additional Link so that the user can select all products, regardless of category. The Link components are styled so they appear as buttons, and the URLs that the browser will navigate to are the combination of a prop called baseUrl and the name of the category.
A relationship is created between the two components: the Shop component is the parent of the ProductList, and the ProductList component is the child of the Shop. Parents configure their child components by providing props, and in Listing 5-16, the Shop component passes on the products prop it received from its parent to its ProductList child component, which will be used to display the list of products to the user. The relationships between components and the ways they can be used to create complex features are described in Part 2 of this book.

Connecting an application to its services
The advantage of this approach is that it simplifies adding features or making changes to the application because the components that present content to the user receive their data via props without the need to obtain it directly from the data store or the URL routing system. The disadvantage is that the component that connects the rest of the application to its services can be difficult to write and maintain, as it must combine the features of different packages and present them to its children. The complexity of this component will increase until the end of Chapter 6, when I consolidate the code around the final set of SportsStore shopping features.
The component in Listing 5-17 connects the Redux data store and the URL router to the Shop component. The Redux package provides the connect function, which is used to link a component to a data store so that its props are either values from the data store or functions that dispatch data store actions when they are invoked, as described in Chapter 20. It is the connect function that has led to much of the code in Listing 5-17 because it requires mappings between the data store and the component’s props, which can be verbose. The mappings in Listing 5-17 give the Shop component access to all of the properties defined in the data store, which consists of the product and category data at present but will include other features later.
You can be more specific in the data store properties you map to props, as demonstrated in Chapter 20, but I have mapped all of the products, which is a useful approach when you start developing a new project because it means you don’t have to remember to map new properties each time you enhance the data store.
The path prop tells the Route to wait until the browser navigates to the /shop/products URL. If there is an additional segment in the URL, such as /shop/products/running, then the contents of that segment will be assigned to a parameter named category, which is how the user’s category selection will be determined.
This is the point at which the data store and the URL routing features are combined. The Shop component needs to know which category the user has selected, which is available through the argument passed to the Route component’s render prop. The category is combined with the data from the data store both of which are passed on to the Shop component. The order in which props are applied to a component allows props to be overridden, which I have relied on to replace the products data obtained from the data store with the result from the filterProduct function, which selects only the products in the category chosen by the user.
The Route is used in conjunction with Switch and Redirect components, both of which are part of the React Router package and which combine to redirect the browser to /shop/products if the browser’s current URL isn’t matched by the Route.
The ShopConnector component uses the componentDidMount method to load the data into the data store. The componentDidMount method is part of the React component lifecycle, which is described in detail in Chapter 13.

Creating the basic shopping features
The category selection buttons work but don’t clearly reflect the current category to the user. To remedy this, I added a file called ToggleLink.js to the src folder and used it to define the component shown in Listing 5-19.
I added this component to the src folder because I will use it for other parts of the application once the shop has been completed. There are no hard-and-fast rules about how a React project is organized, but I tend to keep related files grouped together in folders.

Highlighting the selected component
The shopping cart will allow the user to select several products in a single purchase before checking out. In the sections that follow, I add extend the data store to keep track of the user’s product selections and create components that provide detailed and summary cart views.
The new actions will allow products to be added and removed from the cart and for the entire cart content to be cleared.
The reducer for the cart actions keeps track of the user’s product selection by adding a cart property to the data store and assigning it an array of objects that have product and quantity properties. There are also cartItems and cartPrice properties that keep track of the number of items in the cart and their total price.
It is important to keep the structure of your data store flat because changes deep in an object hierarchy won’t be detected and displayed to the user. It is for this reason that the cart, cartItems, and cartPrice properties are defined alongside the products and categories properties in the data store, rather than grouped together into a single structure.
The component defined in Listing 5-26 receives the data it requires through cartItems and cartPrice props, which are used to create a summary of the component, along with a Link that will navigate to the /shop/cart URL when clicked. The Link is disabled when the value of the items prop is zero to prevent the user from progressing without selecting at least one product.
The i element used as the content of the Link applies a cart icon from the Font Awesome package added to the project in Listing 5-2. See https://fontawesome.com for more details and the full range of icons available.
React handles many aspects of web application development well, but there are some common tasks that are harder to achieve than you might be used to. One example is conditional rendering, where a data value is used to select different content to present to the user or different values for props. The cleanest approach in React is to define a method that uses JavaScript to return a result expressed as HTML, like the getSummary and getLinkClasses methods in Listing 5-26, which are invoked in the component’s render method. The other approach is to use the && operator inline, which works well for simple expressions.
React provides props that are used to register handlers for events, as described in Chapter 12. The handler for the click event, which is triggered when an element is clicked, is onClick, and the function that is specified invokes the addToCart prop, which is mapped to the data store action creator of the same name.

Adding a product to the cart
The CartDetails component presents a table to the user, along with Link components that return to the product list or navigate to the /shop/checkout URL, which starts the checkout process.
The render method must return a single top-level element, which is inserted into the HTML in place of the component’s element when the HTML document is produced, as explained in Chapter 9. It isn’t always possible to return a single HTML element without disrupting the content layout, such as in this example, where multiple table rows are required. For these situations, the React.Fragment element is used. This element is discarded when the content is processed and the elements it contains are added to the HTML document.

Integrating the cart into the SportsStore project
The Checkout button returns the user to the /store/products URL at the moment, but I add support for checking out in Chapter 6.
In this chapter, I started development of a realistic React project. The first part of the chapter was spent setting up the Redux data store, which introduces a range of terms—actions, action creators, reducers—that you may not be familiar with but which will soon become second nature. I also set up the React Router package so that the browser’s URL can be used to select the content and data that is presented to the user. The foundation these features provides takes time to set up, but you will see that it starts to pay dividends as I add further features to SportsStore. In the next chapter, I add further features to the SportsStore application.
In this chapter, I continue adding features to the SportsStore application I created in Chapter 5. I add support for retrieving data from a web service, presenting larger amounts of data in pages and checking out and placing orders.
No preparation is required for this chapter, which uses the SportsStore project created in Chapter 5. To start the React development tools and the RESTful web service, open a command prompt, navigate to the sportsstore folder, and run the command shown in Listing 6-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the SportsStore application
The basic structure of the SportsStore application is taking shape, and I have enough functionality in place to remove the placeholder data and start using the RESTful web service. In Chapter 7, I use GraphQL, which is a more flexible (and complex) alternative to REST web services, but regular web services are common, and I am going to use a REST web service to provide the SportsStore application with its product data and to submit orders at the end of the checkout process.
The web service responds to requests using the JSON data format, which is easy to deal with in a React application since it is similar to the JavaScript object literal form described in Chapter 4. In the sections that follow, I’ll create a foundation for working with the web service and use it to replace the static data that is currently displayed by the SportsStore application.
When I prepare the SportsStore application for deployment in Chapter 8, I will be able to configure the URLs required to access the web service in one place. I have used the data types already defined for the data store for consistency, which helps keeps references to the different types of data consistent and reduces the risk of a typo.
The RestDataSource class uses the Axios package to make HTTP requests to the web service. Axios is described in Chapter 23 and is a popular package for handling HTTP because it provides a consistent API and automatically processes responses to transform JSON into JavaScript objects. In Listing 6-3, the GetData method uses Axios to send an HTTP request to the web service to get all of the available objects for a specified data type. The result from the GetData method is a Promise that is resolved when the response is received from the web service.
HTTP requests sent by JavaScript code are performed asynchronously. This doesn’t fit well with the default behavior of the Redux data store, which responds to changes only when an action is processed by a reducer.
Redux data stores can be extended to support asynchronous operations using a middleware function, which inspects the actions that are sent to the data store and alters them before they are processed. In Chapter 20, I create data store middleware that intercepts actions and delays them while it performs asynchronous requests to get data.
The applyMiddleware is used to wrap the middleware so that it receives the actions, and the result is passed as an argument to the createStore function that creates the data store. The effect is that the asyncActions function defined in Listing 6-4 will be able to inspect all of the actions sent to the data store and seamlessly deal with those with a Promise payload.

Using data from a web service

Generating more data for testing pagination
The code in Listing 6-7 creates 503 product objects. It is a good idea to use numbers of objects that are not divisible by the size of the pages you intend to support so that you can be sure that your code deals with a few stragglers on the last page.
Pagination requires support from the server so that it provides the client with the means to request a subset of the available data and information about how much data is available. There is no standard approach to providing pagination, and you should consult the documentation for the server or service you are using.
Name | Description |
|---|---|
category_like | This field filters the results to include only those objects whose category property matches the field value, which is Watersports in the example URL. If the category field is omitted, then products from all categories will be included in the results. |
_page | This field selects the page number. |
_limit | This field selects the page size. |
_sort | This field specifies the property by which the objects will be sorted before being paginated. |
These are not the only headers in the response, but they have been added specifically to help the client with future pagination requests. The X-Total-Count header provides the total number of objects that are matched by the request URL, which is useful for determining the total number of pages. Since there is no category field in the URL in Listing 6-9, the server has reported that 503 objects are available.
The Link header provides a set of URLs that can be used to query the first and last pages, and the pages before and after the current pages, although clients are not required to use the Link header to formulate subsequent requests.
This component renders the content its parent provides between the start and end tags using the children props. This is useful for defining components that provide services to the application but that don’t present content to the user. In this case, I need a component that can receive details of the current route and its parameters and also access the data store. The component’s componentDidMount and componentDidUpdate methods, both part of the component lifecycle described in Chapter 13, call the getData method, which gets the parameters from the URL and compares them with those in the data store that were added after the last request. If there has been a change, a new action is dispatched that will load the data the user requires.
In addition to the category and page number, which are taken from the URL, the action is created with _sort and _limit parameters that order the results and set the data size. The values used for sorting and for setting the page size will be obtained from the data store.
I have updated the routing configuration to support pagination. The first routing change is the addition of a Redirect, which matches URLs that have a category but no page and redirects them to the URL for the first page of the selected category. I also changed the existing Redirect so that it redirects any unmatched URLs to /shop/products/all.

Requesting pages of data from the web service
The PaginationControls component uses select elements to allow the user to change the page size and the property used to sort the results. The option elements that provide the individual values that can be selected can be configured using props, which will allow me to reuse this component for the administration features in Chapter 7. If no props are supplied, then default values suitable for paginating products are used.
The onChange prop is applied to the select elements to respond to user changes, which are handled by methods that receive the event triggered by the change and invoke function props that are received from the parent component.
Creating the pagination buttons is a complex process, and it is easy to get bogged down in the detail. The approach I have taken in Listing 6-20 aims to strike a balance between simplicity and providing the user with enough context to navigate through large amounts of data.

Adding support for paginating products
The core features of the application are in place, allowing the user to filter and navigate through the product data and add items to a basket that are displayed in summary and detailed views. Once the user completes the checkout process, a new order must be sent to the web service, which will complete the shopping, reset the user’s cart, and display a summary message. In the sections that follow, I add support for checking out and placing an order.
To complete a SportsStore order, the user must complete a form with their personal details, which means that I must present the user with a form. React supports two ways to use form elements: controlled and uncontrolled. For a controlled element, React manages the element’s content and responds to its change events. The select elements used for configuring pagination fall into this category. For the checkout form, I am going to use uncontrolled elements, which are not closely managed by React and rely more on the browser’s functionality. The key to using uncontrolled for elements is a feature called refs, described in Chapter 16, which allow a React component to keep track of the HTML elements that are produced by its render method after they have been displayed to the user. For the checkout form, the advantage of using refs is that I can validate the form using the HTML5 validation API, which I describe in Chapter 15. The validation API requires direct access to the form elements, which wouldn’t be possible without the use of refs.
There are packages available for creating and validating forms in React applications, but they can be awkward to use and apply restrictions on the appearance of the form or the structure of the data that it produces. It is easy to create custom forms and validation using the features described in Chapters 15 and 16, which is the approach I have taken for the SportsStore chapter.
The ValidatedForm component receives a data model and uses it to create a form that is validated using the HTML5 API. Each form element is rendered with a label and a ValidationError component that displays validation messages to the user. The form is displayed with buttons that cancel or submit the form using callback functions provided as props. The submit callback will not be invoked unless all of the elements meet their validation constraints.
When the submit callback is invoked, it will receive an object whose properties are the name attribute values for the form elements and whose values are the data entered into each field by the user.
The Checkout component uses a ValidatedForm to present the user with fields for their name, email, and address. Each form element will be created with the required attribute, and the type attribute of the input element for the email address is set to email. These attributes are used by the HTML5 constraint validation API and will prevent the user from placing an order unless they provide a value for all fields and enter a valid email address into the email field (although it should be noted that only the format of the email address is validated).
The handleSubmit method will be invoked when the user submits valid form data. This method receives the form data and combines it with details of the user’s cart before calling the placeOrder and clearCart action creators and then navigating to the /shop/thanks URL.
The Thanks component displays a simple message and includes the value of the id property from the order object, which it obtains through its order prop. This component will be connected to the data store, and the order object it contains will have an id value that is assigned by the RESTful web service.

Validation errors when checking out
Validation is performed only when the user clicks the button. See Chapters 15 and 16 for examples of validating the contents of a form element after each keystroke.

Placing an order
Each time you place an order, it will be assigned an id by the RESTful web service, which will then be displayed in the order summary.
The data used by the web service is regenerated each time that the development tools are started with the npm start command, which makes it easy to reset the application. In Chapter 8, I switch the SportsStore application to a persistent database as part of the preparations for deployment.
All of the features required by the shopping part of the SportsStore application are complete, but I am going to make one more change in this chapter.
A React application is driven by its props, which provide components with the data and functions they require. When features like URL routing and a data store are used, the point where their capabilities are translated into props can become complex. For the SportsStore application, that is the ShopConnector component, which incorporates data store properties, action creators, and URL routing for the shopping part of the application. The advantage of consolidating these features is that the other shopping components are simpler to write, maintain, and test. The disadvantage is that consolidation results in code that is hard to read and where errors are likely to arise.
In Chapter 9, I explain how JSX is translated into JavaScript, but it is easy to forget that all components can be restructured to rely less on the declarative nature of HTML elements and more on pure JavaScript. In Listing 6-34, I have collapsed the multiple Route components into one whose render function selects the component that should be displayed to the user and provides it with props from the data store and URL router. I have also changed the import statements for the action creators and used the spread operator when mapping them to function props, which I didn’t do earlier because I wanted to show how I connected each data store feature to the rest of the application.
In this chapter, I continued the development of the SportsStore folder, adding support for working with the RESTful web server, scaling up the amount of data that the application can deal with, and adding support for checking out and placing orders. In the next chapter, I add the administration features to the SportsStore application.
In this chapter, I add the administration features to the SportsStore application, providing the tools required to manage orders and products. I use GraphQL in this chapter rather than expanding the RESTful web service I used for the customer-facing part of SportsStore. GraphQL is an alternative to conventional web services that puts the client in control of the data it receives, although it requires more initial setup and can be more complex to use.
This chapter builds on the SportsStore project created in Chapter 5 and modified in Chapter 6. To prepare for this chapter, I am going to generate a number of fake orders so there is data to work with, as shown in Listing 7-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application
The administration features that I add to the SportsStore application in this chapter will use GraphQL instead of a RESTful web service. Few real applications would need to mix REST and GraphQL for the same data, but I want to demonstrate both approaches to remote services.
GraphQL isn’t specific to React development, but it is so closely associated with React that I included an introduction to GraphQL in Chapter 24 and demonstrated the different ways a GraphQL service can be consumed by a React application in Chapter 25.
I am going to create a custom GraphQL server for the SportsStore application so that I can share data with the RESTful web service provided by the excellent json-server package. As I explain in Chapter 24, there are open source and commercial GraphQL servers available.
The GraphQL specification includes a schema language used to define the features that a service provides. The schema in Listing 7-3 defines queries for products, categories, and orders. The product and order queries support pagination and return results that include a totalSize property that reports the number of items available so the client can present the user with pagination controls. The products can be filtered by category, and the orders can be filtered so that only unshipped orders are shown.
The schema in Listing 7-4 defines mutations for storing new products, updating and deleting existing products, and marking orders as shipped or unshipped.
The code in Listing 7-5 implements the queries defined in Listing 7-3. You can see an example of a stand-alone custom GraphQL server in Chapter 24, but the code in Listing 7-5 relies on the Lowdb database that the json-server package uses for data storage and that is described in detail at https://github.com/typicode/lowdb .
Each query is resolved using a series of functions invoked when the client requests specific fields, ensuring that the server has to load and process only the data that is needed. For the orders query, for example, the chain of functions ensures that the server only has to query the database for the related product objects if the client asks for them, avoiding retrieving data that is not required.
Each of the functions defined in Listing 7-6 corresponds to a mutation defined in Listing 7-4. The code required to implement the mutation is simpler than the queries because the queries required additional statements to filter and page data.

The GraphiQL browser
The package I used to create the GraphQL server includes the GraphiQL browser, which makes it easy to explore a GraphQL service. Replace the welcome message in the left part of the window with the GraphQL mutation shown in Listing 7-9.
The data used by the RESTful web service and GraphQL service is reset each time the npm start command 2 is used, which means that the change made by the mutation in Listing 7-9 will be lost when you next start the server. I convert the SportsStore application to a persistent database as part of the deployment preparations in Chapter 8.

The effect of a GraphQL mutation
GraphQL requires more work at the server to create the schema and write the resolvers, but the benefit is that the client can be much simpler than one that uses a RESTful web service. In part, this is because of the way that GraphQL uses well-defined but flexible queries, but it is also because the GraphQL client package provides a lot of useful features that I had to create manually in Chapters 5 and 6.
The way that I use GraphQL in the SportsStore chapter is the simplest approach, but it hides the detail of how GraphQL works. In Chapter 25, I demonstrate how to use GraphQL directly over HTTP and also how to integrate GraphQL into an application that uses a data store.
GraphQL queries are defined as JavaScript string literals in the client application but must be processed using the gql function from the graphql-tag package. The query in Listing 7-12 targets the server’s orders query and will accept variables that are used for the query’s onlyShipped, page, pageSize, and sort parameters. The client query selects only the fields it requires and incorporates details of the product data related to each order, which is included in the query results generated by the server’s resolver for the orders query.
The graphql function accepts arguments for the query and a configuration object and returns a function that is used to wrap a component and provide it access to the query features. There are many properties supported by the configuration object, but I require only two. The first is the options property, which is used to create the set of variables that will be applied to the GraphQL query, using a function that receives the props applied by the parent component.
The Apollo GraphQL client caches the results from queries so that it doesn’t send duplicate requests to the server, which is useful when using components with routing, for example.
The second is the props property, which is used to create the props that will be passed to the display component and is provided with a data object that combines details of the query progress, the response from the server, and the functions used to refresh the query.
The value of the totalSize prop is zero until the result from the server has been received and is then assigned the value of orders.totalSize.
I pass all of the query variables to the refetch function for brevity, but any values the function receives are merged with the original variables, which can be useful for more complex queries.
There is also a fetchMore function available that can be used to retrieve data and merge it with existing results, which is useful for components that gradually build up the data they present to the user. I have taken a simpler approach for the SportsStore application, and each page of data replaces the previous query results.
GraphQL requires only one URL because, unlike REST, it doesn’t use the URL or the HTTP method to describe an operation. In Chapter 8, I will change the URLs used by the application as I prepare the project for deployment.

Making a GraphQL query from a component

Using a mutation
The Apollo client automatically updates its cache of data when there is a change, which means that the change to the value of the shipped property is automatically reflected in the data displayed by the OrdersTable component.
The ProductsTable component receives an array of objects through its products prop and uses the ProductsRow component to generate a table row for each of them. There is also a Link styled as a button that will be used to navigate to the component that will allow new products to be created.
Table cells are rendered for the id, name, category, and price properties. There is a button that invokes a function prop named deleteProduct that will remove a product from the database, and there is a Link that will navigate to the component used to edit product details.
The new mutations correspond to the server-side GraphQL defined at the start of the chapter and allow the client to store a new product, edit an existing product, and delete a product.
This function reads the cached data, removes an object, reduces the totalSize to reflect the deletion, and then writes the data back to the cache, which will have the effect of updating the product list without needing to query the server.
The downside of this approach is that it doesn’t repaginate the data to reflect the deletion, which means that the page displays fewer items until the user navigates to another page. In the next section, I demonstrate how to address this by clearing the cached data, which leads to an additional GraphQL query but ensures that the application is consistent.
The Query component is provided as an alternative to the graphql function and allows GraphQL queries to be performed declaratively, with the results and other client features presented through a render prop function, which is described in Chapter 14. The ProductEditor component defined in Listing 7-24 will obtain the id of the product that the administrator wants to edit and obtains it using the Query component, which is configured using its query and variables props. The render prop function receives an object with loading and data properties, which have the same purpose as for the graphql function I used earlier. The ProductEditor component renders no content while the loading property is true and then displays a ProductCreator component, passing the data received from the query through the prop named product.
The ProductCreator component relies on the ValidatedForm that I created in Chapter 6 to handle checkout from the shopping part of the application. The form is configured with the fields required to edit a product, which will include the values obtained from the GraphQL query when they are provided through the product prop.
I have highlighted the section of code that sets up the function prop that is passed to the ValidatedForm component and that sends the mutation when it is invoked. When an object is updated, the Apollo client automatically updates its cached data to reflect the change, just as when I marked orders as shipped earlier in the chapter. New objects are not automatically processed, which means that the application has to take responsibility for managing the cache. The approach I took for deleting an object was to update the existing cache, but that is a much more complex process for a new item because it means trying to work out whether it should be displayed on the current page and, if so, where in the sort order it would appear. As a simpler alternative, I have received a client parameter from the render prop function, which allows me to clear the cached data through its resetStore method. When the navigate function sends the browser back to the product list, a fresh GraphQL will be sent to the server, which ensures that the data is consistently paged and sorted, albeit at the cost of an additional query.

The product administration features

Creating a new product
In this chapter, I added the administration features to the SportsStore application. I started by creating a GraphQL service with the queries and mutations required to manage the order and products data. I used the GraphQL service to expand the application features, relying on the GraphQL client to manage the data in the application so that I didn’t need to create and manage a data store. In the next chapter, I add authentication for the administration features and prepare the application for deployment.
In this chapter, I add authentication to the SportsStore application to protect the administration features from unauthorized use. I also prepare the SportsStore application for deployment into a Docker container, which can be used on most hosting platforms.
HTTP Method | URL | Description |
|---|---|---|
GET | /api/products | This combination is used to request pages of products for shoppers. |
GET | /api/categories | This combination is used to request the set of categories and is used to provide shoppers with navigation buttons. |
POST | /api/orders | This combination is used to submit orders. |
POST | /login | This combination will be used to submit a username and password for authentication. |
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Name | Description |
|---|---|
name | admin |
password | secret |
All of the server-side code in the SportsStore project can be used for real projects except Listing 8-1, which contains hard-coded credentials and is unsuitable for anything other than basic development and testing.

Running the example application

Encountering an error
In the sections that follow, I explain how the SportsStore application will authenticate users and implement the required features to prevent the error shown in the figure and restore the administration features for authenticated users.
Username | Password |
|---|---|
admin | secret |
I configured the JWT tokens returned by the server so they expire after one hour.
The SportsStore application needs to be able to determine whether the user has been authenticated and keep track of the web token that must be included in HTTP requests, ensuring that the administration features are shown only after successful authentication.
This component uses the React context feature in its render method to provide an implementation of the AuthContext properties and functions, which it does through the value prop of the special AuthContext.Provider element. The effect is to share access to the state data and the authenticate and signout methods directly to any descendant component that applies the corresponding AuthContext.Consumer element, which I will use shortly.
The implementation of the authenticate method uses the Axios package to send a POST request to validate credentials that will be obtained from the user. The result of the authenticate method is a Promise that will be resolved when the server responds to confirm the credentials and will be rejected if the credentials are incorrect.
The context features rely on a render prop function, which can be difficult to integrate directly into components. Using the authWrapper function will allow a component to receive the features defined by the AuthContext as props. (Higher-order components and render prop functions are both described in Chapter 14.)
This component receives routing features from the withRouter function and authentication features from the authWrapper function, both of which will be presented through the component’s props. The ValidatedForm I defined in Chapter 6 is used to present the user with username and password fields, both of which require values. When the form data is submitted, the authenticate method forwards the details for authentication. If authentication is successful, then the history object provided by the URL routing system (described in Chapters 21 and 22) is used to redirect the user to the /admin URL. An error message is displayed if authentication fails.
The Admin component is wrapped with the authWrapper function so it has access to the authentication features. The ApolloClient object is created in the constructor so that I can add a function that modifies each request to add an Authorization header to each GraphQL HTTP request.
There are two new code fragments in the render method. The first displays a logout button if the user is authenticated. The second fragment checks the authentication status and produces a Route component that displays the AuthPrompt component, regardless of the URL. (A Route component without a path property will always display its component and can be used with a Switch to prevent other Route components from being evaluated.)

Authenticating to use the administration features
In the sections that follow, I prepare the SportsStore application so that it can be deployed.
The data file that is used by the RESTful and GraphQL services uses JavaScript to generate the same data each time the server is started. This has been useful during development because it has made it easy to return to a known state, but it isn’t suitable for a production application.
The build process can take a moment to complete, and the result is an optimized set of files in the build folder.
The connect-history-api-fallback package responds to any HTTP request with the contents of the index.html file. This is useful for applications that use URL routing because it means that users can navigate directly to the URLs to which the application navigates using the HTML5 History API.

Testing the application
To complete this chapter, I am going to create a container for the SportsStore application so that it can be deployed into production. At the time of writing, Docker is the most popular way to create containers, which is a pared-down version of Linux with just enough functionality to run the application. Most cloud platforms or hosting engines have support for Docker, and its tools run on the most popular operating systems.
The first step is to download and install the Docker tools on your development machine, which is available from www.docker.com/products/docker . There are versions for macOS, Windows, and Linux, and there are some specialized versions to work with the Amazon and Microsoft cloud platforms. The free Community edition is sufficient for this chapter.
One drawback of using Docker is that the company that produces the software has gained a reputation for making breaking changes. This may mean that the example that follows may not work as intended with later versions. If you have problems, check the repository for this book for updates ( https://github.com/Apress/pro-react-16 ) or contact me at adam@adam-freeman.com.
The devDependencies section species the packages required to run the application in the container. All of the packages that are used in the browser have been included in the JavaScript files produced by the build command. The other fields describe the application, and their main use is to prevent warning when the container is created.
The contents of the Dockerfile use a base image that has been configured with Node.js and copies the files required to run the application, including the bundle file containing the application and the file that will be used to install the NPM packages required to run the application in deployment.
An image is a template for containers. As Docker processes the instructions in the Docker file, the NPM packages will be downloaded and installed, and the configuration and code files will be copied into the image.

Running the containerized SportsStore application
The application is ready to deploy to any platform that supports Docker.
This chapter completes the SportsStore application, showing how a React application can be prepared for deployment and how easy it is to put a React application into a container such as Docker. That’s the end of this part of the book. In Part 2, I begin the process of digging into the details and show you how the features I used to create the SportsStore application work in depth.
Question | Answer |
|---|---|
What are they? | The create-react-app package is used to create projects and set up the tools that are required for effective React development. |
Why are they useful? | Projects created with the create-react-app package are designed for the development of complex applications and provide a complete set of tools for development, testing, and deployment. |
How are they used? | A project is created using the npx create-react-app package, and the development tools are started using the npm start command. |
Are there any pitfalls or limitations? | The create-react-app package is “opiniated,” which means that it provides a specific way of working with few configuration options. This can be frustrating if you are used to a different workflow. |
Are there any alternatives? | You don’t have to use create-react-app to create projects. There are alternative packages available as noted later in this chapter. |
Problem | Solution | Listing |
|---|---|---|
Create a new React project | Use the create-react-app package and add optional packages | 1–3 |
Transform HTML to JavaScript | Use the JSX format to mix HTML and code statements | 6 |
Include static content | Add files to the src folder and incorporate them into the application using the import keyword | 9–10 |
Include static content outside of the development tools | Add files to the public folder and define references using the PUBLIC_URL property | 11–13 |
Disabling linting messages | Add comments to JavaScript files | 15–19 |
Configure the React development tools | Create an .env file and set configuration properties | 20 |
Debug React applications | Use the React Devtools browser extension or use the browser debugger | 22–26 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 9-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
When you create a new project, you may see warnings about security vulnerabilities. React development relies on a large number of packages, each of which has its own dependencies, and security issues will inevitably be discovered. For the examples in this book, it is important to use the package versions specified to ensure you get the expected results. For your own projects, you should review the warnings and update to versions that resolve the problems.
Using the command prompt, run the command shown in Listing 9-4 in the projecttools folder to start the development tools.
Notice that the development tools are started using the npm command and not the npx command that was used in Listing 9-1.

Running the example application

The contents of a new project
You don’t have to use the create-react-app package to create React projects, but it is the most common approach, and it takes care of configuring the build tools that support the features described in this chapter. You can create all of the files and configure the tools directly, if you prefer, or use one of the other techniques available for creating a project, which are described at https://reactjs.org/docs/create-a-new-react-app.html .
Name | Description |
|---|---|
node_modules | This folder contains the packages that the application and development tools require, as described in the “Understanding the Packages Folder” section. |
public | This folder is used for static content and includes the index.html file that is used to respond to HTTP requests, as described in the “Understanding Static Content” section. |
src | This folder contains the application code and content, as described in the “Understanding the Source Code Folder” section. |
.gitignore | This file is used to exclude files and folders from the Git revision control package. |
package.json | This folder contains the set of top-level package dependencies for the project, as described in the “Understanding the Packages Folder” section. |
package-lock.json | This file contains a complete list of the package dependencies for the project, as described in the “Understanding the Packages Folder” section. |
README.md | This file contains information about the project tools, and the same content can be found at https://github.com/facebook/create-react-app . |
Name | Description |
|---|---|
index.js | This file is responsible for configuring and starting the application. |
index.css | This file contains the global CSS styles for the application. See the “Understanding Static Content” section for details of using CSS files. |
App.js | This file contains the top-level React component. Components are described in Chapters 10 and 11. |
App.css | This file contains the placeholder CSS styles for new projects. See the “Understanding Static Content” section for details. |
App.test.js | This file contains unit tests for the top-level component. See Chapter 17 for details of unit testing. |
registerServiceWorker.js | This file is used by progressive web applications, which can work offline. I do not describe progressive applications in this book, but you can find details at https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app . |
logo.svg | This image file contains the React logo and is displayed by the placeholder component added to the project when it is created. See the “Understanding Static Content section. |
JavaScript application development depends on a rich ecosystem of packages, ranging from those that contain the code that will be sent to the browser to small packages that are used behind the scenes during development for a specific task. A lot of packages are required in a React project: the example project created at the start of this chapter, for example, requires more than 900 packages.
There is a complex hierarchy of dependencies between these packages that is too difficult to manage manually and that is handled using a package manager. React projects can be created using two different package managers: NPM, which is the Node Package Manager and that was installed alongside Node.js in Chapter 1, and Yarn, which is a recent competitor designed to improve package management. I use NPM throughout this book for simplicity.
You should use NPM to follow the examples in this book, but you can find details of Yarn at https://yarnpkg.com if you want to use it in your own projects.
When a project is created, the package manager is given an initial list of packages required for React development, each of which is inspected to get the set of packages it depends on. The process is performed again to get the dependencies of those packages and repeated until a complete list of packages is built up. The package manager downloads and installs all of the packages and installs them into the node_modules folder.
The initial set of packages is defined in the package.json file using the dependencies and devDependencies properties. The dependencies section is used to list the packages that the application will require to run. The devDependencies section is used to list the packages that are required for development but that are not deployed as part of the application.
Format | Description |
|---|---|
16.7.0 | Expressing a version number directly will accept only the package with the exact matching version number, e.g., 16.7.0. |
* | Using an asterisk accepts any version of the package to be installed. |
>16.7.0 >=16.7.0 | Prefixing a version number with > or >= accepts any version of the package that is greater than or greater than or equal to a given version. |
<16.7.0 <=16.7.0 | Prefixing a version number with < or <= accepts any version of the package that is less than or less than or equal to a given version. |
~16.7.0 | Prefixing a version number with a tilde (the ~ character) accepts versions to be installed even if the patch level number (the last of the three version numbers) doesn’t match. For example, specifying ~16.7.0 will accept version 16.7.1 or 16.7.2 (which would contain patches to version 16.7.0) but not version 16.8.0 (which would be a new minor release). |
^16.7.0 | Prefixing a version number with a caret (the ^ character) will accept versions even if the minor release number (the second of the three version numbers) or the patch number doesn’t match. For example, specifying ^16.7.0 will allow versions 16.8.0 and 16.9.0, for example, but not version 17.0.0. |
The version numbers specified in the dependencies section of the package.json file will accept minor updates and patches.
Package managers can install packages so they are specific to a single project (known as a local install) or so they can be accessed from anywhere (known as a global install). Few packages require global installs, but one exception is the create-react-app package that I installed in Chapter 1 as part of the preparations for this book. The create-react-app package requires a global install because it is used to create new projects. The individual packages required for the project are installed locally, into the node_modules folder.
Command | Description |
|---|---|
npx create-react-app <name> | This command creates a new React project. |
npm install | This command performs a local install of the packages specified in the package.json file. |
npm install package@version | This command performs a local install of a specific version of a package and updates the package.json file to add the package to the dependencies section. |
npm install --save-dev package@version | This command performs a local install of a specific version of a package and updates the package.json file to add the package to the devDependencies section, which is used to add packages to the project that are required for development but are not part of the application. |
npm install --global package@version | This command will perform a global install of a specific version of a package. |
npm list | This command will list all of the local packages and their dependencies. |
npm run | This command will execute one of the scripts defined in the package.json file, as described next. |
Name | Description |
|---|---|
start | This command starts the development tools, as described in the “Using the React Development Tools” section. |
build | This command performs the build process. |
test | This command runs the unit tests, as described in Chapter 17. |
eject | This command copies the configuration files for all the development tools into the project folder. This is a one-way operation and should be used only when the default configuration of the development tools is unsuitable for a project. |
The commands in Table 9-7 are executed by using npm run followed by the name of the command that you require, and this must be done in the folder that contains the package.json file. So, if you want to run the build command in the example project, you would navigate to the projecttools folder and type npm run build. The exception is the start command, which is executed using npm start.
The key package used by the development tools is webpack, which is the backbone for many JavaScript development tools and frameworks. Webpack is a module bundler, which means that it packages JavaScript modules for use in a browser—although that’s a bland description for an important function, and it is one of the key tools that you will rely on while developing a React application.
When you run the command in Listing 9-5, you will see a series of messages as webpack prepares the bundles required to run the example application. Webpack starts with the index.js file and loads all of the modules for which there are import statements to create a set of dependencies. This process is repeated for each of the modules that index.js depends on, and webpack keeps working its way through the application until it has a complete set of dependencies for the entire application, which is then combined into a single file, known as the bundle.

Using the development tools
Webpack is responsible for the build process, and one of the key steps is code transformation performed by the Babel package. Babel has two important tasks in a React project: transforming JSX content and transforming JavaScript code that uses the latest JavaScript features into code that can be executed by older browsers.
Listing 9-6 and Listing 9-7 produce the same result, and when Babel processes the contents of the App.js file from Listing 9-6, it produces the code from Listing 9-7. When React executes the JavaScript code in the browser, it then uses the DOM API to create the HTML element, as demonstrated in Chapter 3. This may seem like a circular approach, but the JSX transformation is performed only during the build process and is intended to make writing React features easier.
After years of stagnation, the JavaScript language has been revitalized and modernized with features that simplify development and provide features that are common in other programming languages, such as those features described in Chapter 4. Not all recent language features are supported by all browsers, especially older browsers or those used in corporate environments where updates are often rolled out slowly (if at all). Babel solves this problem by translating modern features into code that uses features that are supported by a much wider range of browsers, including those that pre-date the JavaScript renaissance.

Using modern language features

Locating the compiled source code
The Google Chrome developer tools change often, and you may have to hunt around to locate the code produced by Babel. Using Ctrl+F and searching for London is a good way to locate the code you are looking for. An alternative approach is to paste the code from Listing 9-8 into the interpreter at https://babeljs.io/repl , which will produce a similar result.
Some of the features, such as classes, are handled using functions that Babel adds to the bundle sent to the browser. The JSX HTML fragment is translated into a call to the React.createElement method.
The translation of modern features is complex, but recent additions to the JavaScript language are largely syntactic sugar intended to make coding more pleasant for the developer. Translating these features robs the code of these leasing features and requires some contortions to create an equivalent effect that older browsers can execute.
Babel is an excellent tool, but it deals only with JavaScript language features. Babel is not able to add support for recent JavaScript APIs to browsers that do not implement them. You can still use these APIs—as I demonstrated in Part 1 when I used the Local Storage API—but doing so restricts the range of browsers that can run the application.
The development server adds script elements that tell the browser to load the files that contain the React framework, the application code, static content (such as CSS), and some additional features that support the development tools and automatically reload the browser when a change has been detected.
There are two ways to include static content, such as images or CSS stylesheets in a React application. In most circumstances, the best approach is to add the files you need to the src folder and then declare dependencies on them in your code files using import statements.
The style I defined selects img elements and sets the background color and width. In Listing 9-10, I added dependencies to two static files in the src folder to the App component, including the CSS file I updated in the previous listing and the placeholder image added to the project when it is created.
The index.css file is imported by the index.js file, which is the JavaScript file responsible for starting the React application. You can define global styles in the CSS file, and they will be included in the content sent to the browser.
When you use the import keyword to declare a dependency on static content, the decision about how to handle the content is left to the development tools. For files that are smaller than 10Kb, the content will be included in the bundle.js file, along with the JavaScript code required to add the content to the HTML document. This is what happens with the App.css file that was imported in Listing 9-10: the contents of the CSS file will be included in the bundle.js file, along with the code required to create a style element.
For larger files—and any SVG files of any size—the imported file is requested in a separate HTTP request. The relative path specified by the import statement is automatically replaced by a URL that will locate the file, and the file name is changed so that it includes a checksum, which ensures that stale data won’t be cached by the browser.

Static content in the src folder

Static content in the public folder

Following an error to the source code file
You may need to configure the React development tools to specify your editor, as described in the “Configuring the Development Tools” section, and not all editors are supported. Figure 9-8 shows Visual Studio Code, which is one of the editors for which support is provided.
The linter cannot be disabled or reconfigured, which means that you will receive linting warnings for a fixed set of rules, including the no-unused-vars rule, which is the one broken by Listing 9-15. You can see the set of rules that are applied in React projects at https://github.com/facebook/create-react-app/tree/master/packages/eslint-config-react-app .
When you receive a warning, a search for the rule name will provide you with a description of the problem. In this case, a search for no-unused-vars will lead you to https://eslint.org/docs/rules/no-unused-vars , which explains that variables cannot be defined and not used.
The linter will ignore the contents of the App.js file but will still check the contents of the other files in the project.
Linting isn’t the only way to detect common errors and a good complementary technique is static type checking, in which you add details of the data types for variables and function results to your code to create a policy that is enforced by the compiler. For example, you might specify that a function always returns a string or that its first parameter can only be a number. When the application is compiled, the code that uses that function is checked to ensure that it only passes number values as arguments and treats the result only as a string.
The react-scripts-ts value produces a project that is set up with the TypeScript tools and features. You can learn more about TypeScript at https://www.typescriptlang.org .
An alternative is a package called Flow, which is focused solely on type checking and doesn’t have the broader features of TypeScript. You can learn more about Flow at https://flow.org
Name | Description |
|---|---|
BROWSER | This option is used to specify the browser that is opened when the development tools complete the initial build process. You can specify a browser by specifying its path or disable this feature by using none. |
HOST | This option is used to specify the hostname that the development HTTP server binds to, which defaults to localhost. |
PORT | This option is used to specify the port that the development HTTP server uses, which defaults to 3000. |
HTTPS | When set to true, this option enables SSL for the development HTTP server, which generates a self-signed certificate. The default is false. |
PUBLIC_URL | This option is used to change the URL used to request content from the public folder, as described in the Understanding Static Content section. |
CI | When set to true, this option treats all warnings as errors in the build process. The default value is false. |
REACT_EDITOR | This option is used to specify the editor for the feature that opens the code file when you click on a stack trace in the browser, as described in the Understanding the Error Display section. |
CHOKIDAR_USEPOLLING | This option should be set to true when the development tools cannot detect changes to the src folder, which may happen if you are working in a virtual machine or a container. |
GENERATE_SOURCEMAP | Settings this option to false disables the generation of source maps, which the browser uses to correlate the bundled JavaScript code with the source files in the project during debugging. The default is true. |
NODE_PATH | This setting is used to specify the locations that will be searched for Node.js modules. |

Configuring the Development Tools

Adding functionality to the example application
You may find that the browser doesn’t update automatically when the HTTPS option is set to true in the .env file. You can reload the browser manually to see the changes or disable this option and restart the development tools.
The React Devtools browser extension is an excellent tool for exploring the state of a React application. There are versions available for Google Chrome and Mozilla Firefox, and details of the project—including support for other platforms and details of a stand-alone version—can be found at https://github.com/facebook/react-devtools . Once you have installed the extension, you will see an additional tab in the browser’s developer tools window, which is accessed by pressing the F12 button (which is why these are also known as the F12 tools).
The React tab in the F12 tools window allows you to explore and alter the application’s structure and state. You can see the set of components that provide the application functionality, along with their state data and their props.

Exploring components using the React Devtools
If you click the buttons in the browser window, you will see the values displayed by the React Devtools change, reflecting the live state of the application. You can also click a state data value and change its values through React Devtools, which allows the state of the application to be manipulated directly.
There are also debugging tools for the Redux data store package, which I describe in Chapter 19 and which is often used to manage the data for complex projects.
Modern browsers include sophisticated debuggers that can be used to control the execution of an application and examine its state. The React development tools include support for creating source maps, which allow the browser to correlate the minified and bundled code that it is executing with the developer-friendly source code required for productive debugging.

Using the browser debugger
Most browsers ignore the debugger keyword unless the F12 tools window is open, but it is good practice to remove it at the end of a debugging session.
In this chapter, I described the structure of React projects created with the create-react-app package and explained the purpose of the files and folders used in React development. I also explained how the React development tools are used, how applications are bundled for use in the browser, how the error display and linter help avoid common problems, and how you can debug applications when you don’t receive the results you are expecting. In the next chapter, I introduce components, which are the key building block for React applications.
Question | Answer |
|---|---|
What are they? | Components are the key building blocks in React applications. Stateless components are JavaScript functions that render content that React can present to the user. Props are the means by which one component provides data to another so that it can adapt the content it renders. |
Why are they useful? | Components are useful because they provide access to the React support for creating features by combining JavaScript, HTML, and other components. Props are useful because they allow components to adapt the content they produce. |
How are they used? | Stateless components are defined as JavaScript functions that return a React element, which is usually defined using HTML in the JSX format. Props are defined as properties on elements. |
Are there any pitfalls or limitations? | React requires components to behave in specific ways, such as returning a single React element and always returning a result, and it can take time to become used to these restrictions. The most common pitfall with props is specifying literal values when a JavaScript expression was required. |
Are there any alternatives? | Components are the key building block in React applications, and there is no way to avoid their use. There are alternative to props that can be useful in larger and more complex projects, as described in Chapter 14 and in Part 3. |
Problem | Solution | Listing |
|---|---|---|
Add content to a React application | Define a function that returns HTML elements or invokes the React.createElement method | 1–9 |
Add additional features to a React application | Define components and compose them in a parent-child relationship using elements that correspond to the component name | 10–14 |
Configure a child component | Define props when applying the component | 15–19 |
Render HTML elements for each object in a data array | Use the map method to create elements, ensuring that they have a key prop | 20–24 |
Render multiple elements from a component | Use the React.Fragment element or use elements without tags | 25–28 |
Render no content | Return null | 29 |
Receive notifications from a child component | Configure the component with a function prop | 31–34 |
Pass on props to a child | Use the prop values received from the parent or use the destructuring operator | 35–39 |
Define default prop values | Use the defaultProps property | 40, 41 |
Check prop types | Use the propTypes property | 42–44 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 10-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application

Defining and applying a component
As simple as the result might be, it reveals the key purpose of components, which is to provide React with content to display to the user.
When a component renders a string value, it is included as text content in the parent element. Components become more useful when they return HTML content, which is most easily done by taking advantage of JSX and the way it allows HTML to be mixed with JavaScript code. In Listing 10-6, I changed the result of the component so that it renders a fragment of HTML.
You must declare a dependency on React from the react module when you use JSX, as shown in the listing. You will receive a warning if you forget.
You remember to use the return keyword inside the component’s function to render the result. This can feel awkward, but remember that the HTML fragment in a JSX file is converted to a call to the createElement method, which produces an object that React can display to the user.
The component function returns the result from the React.createElement method, which is an element that React can use to add content to the Domain Object Model (DOM).
This allows the HTML elements to be consistently indented, although the dangling ( and ) characters can strike some developers as awkward.
The fat arrow function is assigned to a const that is exported by name, and a separate statement uses the name to create the default export, which allows the component to be imported by name and as the default.
I have included this example because module exports cause confusion, but in real projects they use either named or default exports throughout and don’t have to accommodate both styles of working. I prefer using named exports, and that is the approach I have taken in the examples in this book.

Returning HTML content

Rendering other content

Applying multiple children

Using different child components
Being able to render content from multiple children isn’t that useful when each component renders identical content. Fortunately, React supports props—short for properties—which allows a parent component to provide data to its children, which they can use to render their content. In the sections that follow, I explain how props work and demonstrate the different ways they can be used.
I have provided two props, greeting and name, for each Message component. Most of the prop values are static values, which are expressed as literal strings. The value for the greeting prop on the second Message element is an expression, which concatenates two string values. (You will see a linter warning about the expression in Listing 10-15 because concatenating string literal values is on the list of poor practices that the linter is configured to detect. The linter warning can be ignored for this purposes of this chapter.)
If you don’t get the results you expect, in JSX or pure JavaScript, the React Devtools browser extension (described in Chapter 9) can display the props that are received by each component in the application, which makes it easy to see where things have gone wrong.

Rendering content using props
The prop values provided to each Message element defined by the App component in Listing 10-16 results in different content, allowing the same functionality to be employed by the parent component in different ways.

Using an if statement to select content
I have used the JavaScript ternary conditional operator to select the classes that the h4 element will be assigned to and applied those classes with an expression for the className property. The result is the same as Listing 10-17 but without duplicating the unchanging parts of the HTML element.

Using a switch statement to select content

Creating React elements for the objects in an array
The argument to the map method is a function that is invoked for each object in the array. Each time the function passed to the map method is invoked, the next item in the array is passed to the function, which I use to create the element that represents that object. The result from each call to the function is added to an array that is used as the map result. The code in Listing 10-22 produces the same result as Listing 10-21.
You don’t have to use fat arrow functions with the map method, but it produces a more concise component.
This change doesn’t alter the output and produces the same result as Listing 10-21 and Listing 10-22.
In Listing 10-23, the function I passed to the map method receives the current array object as its argument. The map method also provides two additional arguments: the zero-based index of the current object in the array and the complete array of objects. You can see an example of the array index in the “Rendering Multiple Elements” section later in this chapter.
I used the value of the name variable, to which each object in the array is assigned when the function passed to the map method is invoked and which allows React to differentiate between the elements created from the array objects.
React will display elements that do not have a key prop, as the earlier examples in this section demonstrate, but a warning will be displayed in the browser’s JavaScript console.
React requires components to return a single top-level element, although that element is able to contain as many other elements as the application requires. The Summary component, for example, returns a top-level h4 element that contains a series of div elements that are generated for the elements in the names prop.

Rendering multiple elements
This is equivalent to Listing 10-27 and produces the same result. I use the React.Fragment for the examples in this book or wrap multiple elements in a div where that produces a legal combination of HTML elements.

Rendering no content

Attempting to modify a prop
This error isn’t displayed when the application has been built for deployment using the process described in Chapter 8, which means you should test thoroughly during development to ensure your components don’t inadvertently try to change a prop.
All of the props I have used so far in this chapter have been data props, which provide a child component with a read-only data value. React also supports function props, where the parent component provides a child with a function that it can invoke to notify the parent that something important has happened. The parent component can respond by changing the value of the data props, which will trigger an update and allow the child to present updated content to the user.
The component renders a button element whose onClick prop selects the function prop it receives from its parent. I describe the onClick prop in Chapter 12, but, as you have seen in earlier chapters, this property tells React how to respond when the user clicks an element, and, in this case, the expression tells React to invoke the reverseCallback prop, which is the function that has been provided by the parent component.

Using a function received as a prop
The render method is used to add a component’s content to the Document Object Model (DOM) displayed by the browser and is used in the index.js file to start the application; it is described in Chapter 13. This is not a feature that is normally used directly, but I needed to be able to perform an update in response to the function prop being invoked. I describe the features that are normally used to perform updates in Chapter 11. For the moment, it is enough to know that calling this method updates the HTML elements displayed to the user, reflecting the change in the data values used for prop values.
When the function is selected by an expression, it will be passed an event object, which I describe in Chapter 12 and which provides the function that is invoked with details of the HTML element that triggered the event.

Invoking a function prop with an argument
React will evaluate the expression when the component renders its content, which will invoke the prop even though the user hasn’t clicked the button element. This is rarely the intended effect and can cause unexpected behaviors or produce an error, depending on what the prop does when it is invoked. In the case of the component in Listing 10-34, for example, the effect is to create a “Maximum Update Depth Exceeded” error, which occurs because the function prop asks React to re-render the components, which causes the Summary component to render content, which invokes the prop again. This continues until React halts execution and reports an error.
This component renders a button element whose text content is set using a prop named text and that invokes a function provided through the prop named callback when clicked. There is also a theme prop that is used to select the Bootstrap CSS style for the button element.

Passing on props
The rest operator is used in a statement that creates a childProps object that contains all of the parent’s props except theme. The destructuring operator is used to pass the props from the childProps object to the child component.

Using default prop values
Name | Description |
|---|---|
array | This value specifies that a prop should be an array. |
bool | This value specifies that a prop should be a bool. |
func | This value specifies that a prop should be a function. |
number | This value specifies that a prop should be a number value. |
object | This value specifies that a prop should be an object. |
string | This value specifies that a prop should be a string. |
You can combine any of the types in Table 10-3 with isRequired to generate a warning if a value for that prop isn’t supplied by the parent component: PropTypes.bool.isRequired.
To resolve the problem, I could change the prop value so that it sends the expected type to the component. An alternative approach is to make the component more flexible so that it is able to deal with both Boolean and string values for the disabled prop. Given how common it is to create string prop values when Boolean values are required, this is a good idea, especially if you are writing components that are going to be used by other development teams. In Listing 10-44, I have added support to the SimpleButton component for dealing with both types and updated its propTypes configuration to reflect the change.
The prop type checks are performed only during development and are disabled when the application is prepared for deployment. See Chapter 8 for an example of preparing an application for deployment.
Name | Description |
|---|---|
oneOfType | This method accepts an array of PropTypes values that the component is willing to receive. |
oneOf | This method accepts an array of values that the component is willing to receive. |

Accepting multiple prop types
The alternative approach would have been to change the prop value to a Boolean when applying the component, which can be done using an expression for the disabled property: disabled={ true }.
In this chapter, I introduced stateless components, which are the simplest version of the key building block in React applications. I demonstrated how stateless components are defined, how they render content, and how components can be combined to create more complex features. I also explained how a parent component is able to pass on data to its children using props and showed you how props can also be used for functions, which provides the basic features required for communication between components. I finished this chapter by showing you the features that define default values and types for props. In the next chapter, I explain how to create components that have state data.
Question | Answer |
|---|---|
What are they? | Components are the key building blocks in React applications. Stateful components have their own data that can be used to alter the content the component renders. |
Why are they useful? | Stateful components make it easier to keep track of the application state provided by each component and provide the means to alter the data values and reflect the change in the content presented to the user. |
How are they used? | Stateful components are defined using a class or by adding hooks to a functional component. |
Are there any pitfalls or limitations? | Care must be taken to ensure that state data is modified correctly, as described in the “Modifying State Data” section of this chapter. |
Are there any alternatives? | Components are the key building block in React applications, and there is no way to avoid their use. There are alternative to props that can be useful in larger and more complex projects, as described in later chapters. |
Problem | Solution | Listing |
|---|---|---|
Add state data to a component | Define a class whose constructor sets the state property or call the useState function to create a property and function for a single state property | 4–5, 12, 13 |
Modify state data | Call the setState function or call the function returned by useState | 6–11 |
Share data between components | Lift the state data to an ancestor component and distribute it using props | 14–18 |
Define prop types and default values in a class-based component | Apply the properties to the class or define static properties within the class | 19–20 |
In this chapter, I continue using the components project created in Chapter 10. To prepare for this chapter, I changed the content rendered by the Summary component so that it uses the SimpleButton component directly as shown in Listing 11-1, rather than the CallbackButton that I used to describe how props are distributed.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application
In the sections that follow, I explain the differences between the types of component that React supports. Understanding how stateful components work will be easier when you see the key difference from the stateless components described in Chapter 10.

Predictable results from a stateless component
A stateless component will always render the same HTML elements given the same set of prop values, regardless of how often the function is invoked. It depends entirely on the prop values provided by the parent component to render its content. This means that React can keep invoking the same function regardless of how many SimpleButton elements there are in the application and just has to keep track of which props are associated with each SimpleButton element.
A stateful component has its own data that influences the content the component renders. This data, which is known as state data, is separate from the parent component and the props it provides.
Imagine that the SimpleButton component has to keep track of how many times the user has clicks the button element it renders and displays the current count as the element’s content. To provide this feature, the component needs a counter that is incremented each time the button is clicked and must include the current value of the counter when it renders its content.

Stateful components with a counter
There is no longer any certainty that providing the same prop to a stateful component will render the same result because each component object can have different values for its state data and use it to generate different results.
As you will learn, stateful components have many features that are not available in stateless components, and you will find that these features are easier to understand if you remember that each stateful component is a JavaScript object with its own state data and is associated with a single custom HTML element.
To get started, I am going to convert one the existing SimpleButton component in the example application from a stateless to stateful component, which will let me explain the basics before moving on to more complicated features.
Defining a stateful component is done using a class, which is a template that describes the functionality that each component object will have, as described in Chapter 4. In Listing 11-4, I have replaced the SimpleButton component’s function with a class.
This is a stateful component that doesn’t have any state data. I explain how to define the component and then show you how to add state data in the “Adding State Data” section.
In the sections that follow, I describe each of the changes made in Listing 11-4 and explain how they are used to create a stateful component.
This combination of keywords defines a class called SimpleButton that extends the Component class provided by React. The export keyword makes the SimpleButton class available for use outside of the JavaScript file in which it is defined, just as it did when the component was defined as a function.
As I explained in Chapter 4, there are two types of import in this statement. The default export from the react package is imported and assigned the name React, which allows JSX to work. The react package also has an export named Component that is imported using curly braces (the { and } characters). It is important that you use the import statement exactly as shown when you create a stateful component.

Introducing a stateful component
State data is defined using a constructor, which is a special method that is invoked when a new object is created using the class and that must follow the form shown in the listing: the constructor should define a props parameter, and the first statement should be a call to the special super method using the props object as an argument, which invokes the constructor of the Component class and sets up the features available in a stateful component.
The state data is defined as properties on the object. There is one property in this example, and it creates state data properties called counter, whose value is 0, and hasButtonBeenClicked, whose value is false.

Defining and reading state data
React doesn’t allow state data to be modified directly and will report an error if you try to assign a new value directly to a state property. Instead, modifications are made through the setState method, which is inherited from the Component class. In the listing, I have added a method called handleClick that is selected by the button element’s onClick expression and that uses the setState method to increment the counter state property.
Methods that are selected by the onClick property have to be defined in a specific way. I explain how the onClick property is used and how its methods are defined in Chapter 12.
This statement tells React that the counter property should be modified by incrementing the current value and that the hasButtonBeenClicked property should be true. Notice that I have not used the increment operator (++) for counter because that would assign a new value to the property and result in an error.
You only have to define properties for the values you want to change when using the setState method. React will merge the changes you specify with the rest of the component’s state data and leave unchanged any property for which a value has not been provided.

Modifying state data
Clicking a button changes the state of one of the component objects and leaves the other five component objects unchanged.
React performs changes to state data asynchronously and may choose to group together several updates to improve performance, which means that the effect of a call to the setState may not take effect in the way you expect. There are some common pitfalls when updating state data, which I describe in the sections that follow, along with details of how to avoid them.
The React Devtools browser extension shows you the state data for a stateful component, which can be a useful way of seeing how the application responds to changes and tracking down problems when you don’t get the behavior you expect.

The dependent value pitfall

Forcing state changes to be performed in sequence

Applying multiple updates to a state property
If you need to perform multiple updates and have each take effect in sequence, then you can use the version of the setState method that accepts a function as its first argument. The function is provided with the current state data and a props object, as shown in Listing 11-11.
This version of the setState method is also useful for updating nested state properties, which you can see demonstrated in Chapter 14.

Applying multiple updates to a state property
The use of hooks is not visible to the Summary component, which provides data and functions via props as normal. This example produces the same result, as shown in Figure 11-10.
Hooks offer an alternative approach to creating stateful components for developers who don’t like to use classes. Depending on your personal preference, either this will be an important feature that suits your coding style or you will carry on defining classes and forget about hooks entirely.
The hooks and classes features will both be supported in future versions of React and so you can use whichever suits you best or mix and match freely if you prefer. I like the hooks features, but, aside from describing some related hooks features in Chapter 13, all of the examples in this book use classes. In part that is because the hooks feature is new—but it is also because I have been using class-based programming languages for a long time and using classes to define components suits my way of thinking about code, even for simple stateless components.
If you prefer using hooks but can’t work out how to express the book examples without using a class, then e-mail me at adam@adam-freeman.com, and I will try to point you in the right direction.
At the moment, each SimpleButton and HooksButton component exists in isolation and has its own state data, so clicking a button affects only the state value of a single component and leaves the others unchanged.
A different approach is needed when components need access to the same data. In this situation, the state data is lifted up, which means it is moved to the first common ancestor component and distributed back down to the components that require it using props.
There are alternative approaches available for sharing data between React components. Chapter 13 describes the context feature, and more complex projects can benefit from using a data store (see Chapters 19 and 20) or URL routing (see Chapters 21 and 22).
The Summary component defines a counter property and passes it on to its child components as a prop. The component also defines an incrementCounter method that child components will invoke to change the counter property, which is passed on using a prop named incrementCallback. This is required not only because state data is not modified directly but also because props are read-only. The incrementCounter method uses the setState method with a function so that it can be invoked repeatedly by child components.
I defined a props property in the render method so that I don’t have to change all the references to use the this keyword, which is a useful shortcut when converting a function component to use a class.

Lifting state data
Not every item of state data has to be lifted, and the individual components still have their own local state data, such that the hasButtonBeenClicked property remains local and independent from the other components.
No constructor is required when a stateful component doesn’t have state data, and you will receive a warning if you define a constructor that doesn’t do anything except pass on props to the base class using super. I used the destructuring operator to pass on the props received from the App component to the SimpleButton and HooksButton components.

Lifting state data to the top-level component
No changes are required to the SimpleButton and HooksButton components, which are unaware of where the state data is defined and receive the data values and the callback functions required to change it as props.
These changes don’t alter the appearance of the example application, but they ensure that the component will receive only the prop types it expects and that a default value for the disabled prop is available.
In this chapter, I introduced the stateful component, which has its own data values that can be used to alter the rendered output. I explained that stateful components are defined using classes and showed you how to define state data in a constructor. I also showed you the different ways that state data can be modified and how to avoid the most common pitfalls. In the next chapter, I explain how React deals with events.
Question | Answer |
|---|---|
What are they? | React events are triggered by elements to report important occurrences, most often user interaction. |
Why are they useful? | Events allow components to respond to interaction with the content they render, which forms the foundation for interactive applications. |
How are they used? | Interest in an event is indicated by adding properties to the elements rendered by a component. When an event in which a component is interested is triggered, the function specified by the property is invoked, allowing the component to update its state, invoke a function prop, or otherwise reflect the effect of the event. |
Are there any pitfalls or limitations? | React events are similar to the events provided by the DOM API but with some differences that can present pitfalls for the unwary, especially when it comes to event phases, as described in the “Managing Event Propagation” section. Not all of the events defined by the DOM API are supported (see https://reactjs.org/docs/events.html for a list of events that React supports). |
Are there any alternatives? | There is no alternative to using events, which provide an essential link between user interaction and the content rendered by a component. |
Problem | Solution | Listing |
|---|---|---|
Handle an event | Add the prop that corresponds to the event name and use the expression to process the event | 6–10 |
Determine the event type | Use the event object’s type property | 11 |
Prevent an event from being reset before it is used | Use the event object’s persist method | 12, 13 |
Invoke event handlers with a custom argument | Define an inline function in the prop expression that invokes the handler method with the required data | 14, 15 |
Prevent an event’s default behavior | Use the event object’s preventDefault method | 16 |
Manage the propagation of an event | Determine the event phase | 17–23 |
Stop an event | Use the event object’s stopPropagation method | 24 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 12-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application

Handling an event
This expression results in React invoking the handleEvent method when the component object is created and not when an event is triggered. You won’t receive an error or warning for this mistake, which makes the problem harder to spot.

Binding for an event handler
All three approaches take a while to get used to—and all are a little inelegant—and you should follow the approach that you find most comfortable.
Name | Description |
|---|---|
nativeEvent | This property returns the Event object provided by the DOM API. |
target | This property returns the object that represents the element that is the source of the event. |
timeStamp | This property returns a timestamp that indicates when the event was triggered. |
type | This property returns a string that indicates the event type. |
isTrusted | This property returns true when the event has been initiated by the browser and false when the event object has been created in code. |
preventDefault() | This method is called to prevent an events default behavior, as described in the “Preventing Default Behavior” section. |
defaultPrevented | This property returns true if the preventDefault method has been called on the event object and false otherwise. |
persist() | This method is called to present React from reusing the event object, which is important for asynchronous operations, as described in the “Avoiding the Event Reuse Pitfall” section. |
React events provide an essential link between a component and the content it renders—but React events are not DOM events, even though they appear the same most of the time. If you go beyond the most commonly used features, you will encounter important differences that can produce unexpected results.
First, React doesn’t support all events, which means that there some DOM API events that don’t have corresponding React properties that components can use. You can see the set of events that React supports at https://reactjs.org/docs/events.html . The most commonly used events are included in the list, but not every event is available.
Second, React doesn’t allow components to create and publish custom events. The React model for interaction between components is through function props, described in Chapter 10, and custom events are not distributed when the Event.dispatchEvent method is used.
Third, React provides a custom object as a wrapper around the DOM event objects, which doesn’t always behave in the same way as the DOM event. You can access the DOM event through the wrapper, but this should be done with caution because it can cause unexpected side effects.
Finally, React intercepts DOM events in their bubble phase (described later in this chapter) and feeds them through the hierarchy of components, providing components with the opportunity to respond to events and update the content they render. This means some of the features provided by the event wrapper object don’t work as expected, especially when it comes to propagation, as described in the “Managing Event Propagation” section.

Receiving an event object

Differentiating event types

Asynchronously using event objects

Persisting an event

Using a custom argument
If your handler method doesn’t need the event object, then you can use the inline expression to call the handler without it: () => handleEvent("primary").

Preventing event default behavior
Name | Description |
|---|---|
eventPhase | This property returns the propagation phase of an event. However, the way that React handles events means this property is not useful, as described in the “Determining the Event Phase” section. |
bubbles | This property returns true if the event will enter the bubble phase. |
currentTarget | This property returns an object that represents the element whose event handler is processing the event. |
stopPropagation() | This method is called to stop event propagation, as described in the “Stopping Event Propagation” section. |
isPropagationStopped() | This method returns true if stopPropagation has been called on an event. |
There are two messages in the console because there are two onClick properties in the content rendered by the ThemeButton component. The first message is generated during the target phase when the event is processed by the handlers of the element that triggered it, which is the button element in this example. The event then enters the bubble phase, where it propagates up through the button element’s ancestor and invokes any suitable event handlers. In the example, the span element that is the parent of the button also has an onClick property, which results in two calls to the handleClick method and two messages written to the console.
Not all types of event have a bubble phase. As a rule of thumb, events that are specific to a single element—such as gaining and losing focus—do not bubble. Events that apply to multiple elements—such as clicking a region of the screen that is occupied by multiple elements—will bubble. You can check to see whether a specific event is going to go through the bubble phase by reading the bubbles property of the event object.

The target and bubble phases of the event
Event handling is performed by the HTML elements that are rendered by components and excludes the custom HTML elements that are used to apply components. Adding event handler properties, such as onClick to the ThemeButton element, for example, has no effect. No error is reported, but the custom element is excluded from the HTML that is displayed by the browser, and the handler will never be invoked.

The event capture phase
The SythenticEvent object that React uses defines an eventPhase property, which returns the value of the corresponding property from the native DOM API event object. Unfortunately, the value of that property always indicates that the event is in the bubble phase because React intercepts the native event and uses it to simulate the three propagation phases. As a consequence, a little more work is required to identify event phases.
I used an inline expression for the onClickCapture property that receives the SythenticEvent object and uses it to invoke the handleClick method, along with an additional argument that indicates the event is in the capture phase. Within the handleClick method, I check the value of the capturePhase parameter to identify events in their capture phase.
These messages also confirm the order of the event’s phases: capture, target, and then bubble.

Stopping an event
In this chapter, I described the features that React provides for working with events. I demonstrated the different ways that handler functions can be defined, showed you how to work with event objects, and showed how to use custom arguments instead. I also explained how React events are not the same as DOM API events, even though they are similar and closely related. I finished the chapter by introducing the event lifecycle and showing you how events are propagated. In the next chapter, I describe the component lifecycle and explain how state data changes are reconciled.
Question | Answer |
|---|---|
What is it? | Reconciliation is the process of efficiently handling the content produced by components to minimize changes to the Document Object Model (DOM). Reconciliation is part of a larger lifecycle that is applied to stateful components. |
Why is it useful? | The reconciliation process helps application performance, while the broader component lifecycle provides a consistent model for application development and provides useful features for advanced projects. |
How is it used? | The reconciliation process is performed automatically, and no explicit action is required. All stateful components go through the same lifecycle and can participate actively by implementing specific methods (for class-based components) or the effect hook (for functional components). |
Are there any pitfalls or limitations? | Care must be taken to write components so they fit into the overall lifecycle, which includes being able to render content even though it may not be used to update the DOM. |
Are there any alternatives? | No, the lifecycle and the reconciliation process are fundamental React features. |
Problem | Solution | Listing |
|---|---|---|
Trigger reconciliation | Call the forceUpdate method | 15, 16 |
Respond to lifecycle stages | Implement the method that corresponds to the lifecycle stage | 17–20 |
Receive notifications in a functional component | Use the effect hook | 21–23 |
Prevent updates | Implement the shouldComponentUpdate method | 24, 25 |
Set state data from props | Implement the getDerivedStateFromProps method | 26, 27 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 13-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
This component has its own state data, which it uses to render a list. An ActionButton component is provided with the reverseList method as its function prop, which reverses the order of the items in the list.

Running the example application

Components and their content

Mapping components to the content they render
The browser doesn’t know—or care—about the components, and its only job is to present the HTML elements in the DOM. React is responsible for managing the components and dealing with the content that is rendered.
There are messages from one App component, one Message component, one List component, and two ActionButton components, matching the structure illustrated in Figures 13-2 and 13-3.
When the application first starts, React asks all the components to render their content so that it can be displayed to the user. Once the content is displayed, the application is in the reconciled state, where the content displayed to the user is consistent with the state of the components.

Clicking a button to trigger a change

Clicking a button to trigger a limited change
The List component and its child ActionButton are marked as stale, but the change hasn’t affected the App and Message components or the other ActionButton. React assumes that the content rendered these components is still current and doesn’t need to be updated.
Although React will invoke the render method of any component that has been marked as stale, it doesn’t always use the content that is produced. Making changes to the HTML elements in the Domain Object Model is an expensive operation and so React compares the content returned by the components with the previous results so that it can ask the browser to perform the smallest number of operations, a process known as reconciliation.

The effect of reconciliation
React compares the content produced by components with its own cache of previous results, known as the virtual DOM, which is defined in a format that allows for efficient comparisons. The effect is that React doesn’t have to query the elements in the DOM to figure out the set of changes.
Don’t confuse the term virtual DOM, which is specific to React, with shadow DOM, which is a recent browser feature that allows content to be scoped to a specific part of the HTML document.
The component alternates between displaying a div element directly or wrapping it in a span element. Save the changes and execute the statement shown in Listing 13-12 in the browser’s JavaScript console to set the background color of the div element. Notice that I have defined the callback property after passing on props to the ActionButton component using the spread operator. The Message component receives a callback property from its parent, so I have to define my replacement afterward to override it.
Don’t change the top-level element in components in real projects because it causes React to replace elements in the DOM without performing a detailed comparison to detect changes.

Reconciling different types of element
React compares the output from the render method with the previous results and detects the introduction of the span element. React doesn’t investigate the content of the new span element to perform a more detailed comparison and just uses it to replace the existing div element that the browser is displaying.
The value of the key prop must be unique within the set of elements so that React can identify each one. To demonstrate how React minimizes the changes required to update lists, I added an attribute to the h5 elements rendered by the List component, as shown in Listing 13-13.
Key values should be stable, such that they should continue to refer to the same object even after operations that make changes to the array. A common mistake is to use the position of an object in the array as its index, which is not stable because many operations on arrays affect the order of objects.

Reordering elements in a list
The reconciliation process relies on React being notified of changes through the setState method, which allows it to determine which data is stale. It isn’t always possible to call the setState method if you need to respond to changes that have occurred outside of the application, such as when external data has arrived. For these situations, React provides the forceUpdate method, which can be used to explicitly trigger an update and ensures that any changes are reflected in the content presented to the user. To demonstrate explicit reconciliation, I added a file called ExternalCounter.js to the src folder and used it to define the component shown in Listing 13-15.
It is worth considering the design of your application if you find yourself using the forceUpdate method. The forceUpdate method is a blunt instrument and its use can often be avoided by extending the use of state data or by applying one of the composition techniques described in Chapter 14.

Explicitly starting reconciliation
Most class-based stateful components implement a constructor and the render method. The constructor is used to receive props from the parent and to define state data. The render method is used to produce content, both when the application starts and when React is responding to an update.
Name | Description |
|---|---|
constructor | This special method is called when a new instance of the component class is created. |
render | This method is called when React requires content from the component. |
componentDidMount | This method is called after the initial content rendered by the component has been processed. |
componentDidUpdate | This method is called after React has completed the reconciliation process following an update. |
componentWillUnmount | This method is called before a component is destroyed. |
componentDidCatch | This method is used to handle errors, as described in Chapter 14. |
See the “Using the Effect Hook” section for details of how the hooks feature provides access to the lifecycle features for functional components.

The mounting phase
The constructor is called when React needs to create a new instance of a component, which gives the component an opportunity to receive the props from its parents, define its state data, and perform other preparatory work.
Next, the render method is called so that the component provides React with the content that will be added to the DOM. Finally, React calls the componentDidMount method, which tells the component that its content has been added to the DOM.

Controlling the visibility of a component
Each time the checkbox is toggled on, React creates a new Message object and goes through the mounting process, calling each of the methods in turn: constructor, render, and componentDidMount. This can be seen in the messages displayed in the browser’s JavaScript console.

The update phase
The main use of the componentDidUpdate method is to directly manipulate the HTML elements in the DOM using the React refs feature, which I describe in Chapter 16. For this chapter, I have implemented the method in the Message component and used it to write a message to the browser’s JavaScript console, as shown in Listing 13-19.
The componentDidUpdate method is called even if the reconciliation process determines that the content generated by the component has not changed.
React will not reuse components once they have been unmounted. React will create a new object and perform the mounting sequence if another Message component is required, such as when the checkbox is toggled again. This means you can always rely on the constructor and the componentDidMount methods to initialize a component, and a component object will never be asked to recover from an unmounted state.
Name | Description |
|---|---|
shouldComponentUpdate | This method allows a component to indicate that it does not need to be updated. |
getDerivedStateFromProps | This method allows a component to set its state data values based on the props it receives. |
getSnapshotBeforeUpdate | This method allows a component to capture information about its state before the reconciliation process updates the DOM. This method is used in conjunction with the ref feature, described in Chapter 16. |
React’s default behavior is to mark a component as stale and render its content whenever its state data changes. And, since a component’s state can be passed on to its children as props, the descendant components are rendered as well, as you have seen in earlier examples.
Components can override the default behavior by implementing the shouldComponentUpdate method. This feature allows components to improve the application’s performance by avoiding calls to the render method when they are not required.

The advanced sequence of update methods

Displaying components side by side

Updating state data from props
The getDerivedStateFromProps method is static, which means that it is unable to access any of the instance methods or properties via the this keyword. Instead, the method receives a props object, which contains the props values provided by the parent component, and a state object, which represents the current state data. The getDerivedStateFromProps method returns a new state data object that is derived from the prop data.

Deriving state data from prop values
Notice that I create a new state data object only if the value of the prop is different. Remember that React will trigger a component’s update phase when an ancestor’s state has changed, which means that the getDerivedStateFromProps method may be called even though none of the prop values on which the component depends has changed.
In this chapter, I explained how React deals with the content rendered by components through the reconciliation process. I also described the broader component lifecycle and showed you how to receive notifications in stateful components by implementing methods. In the next chapter, I describe the different ways that components can be combined to create complex features.
Question | Answer |
|---|---|
What is it? | Application composition is the combination of components to create complex features. |
Why is it useful? | Composition makes development easier by allowing small and simple components to be written and tested before being combined to work together. |
How is it used? | There are different patterns available, but the basic approach is to combine multiple components. |
Are there any pitfalls or limitations? | The composition patterns can feel awkward if you are used to deriving functionality from classes, such as in C# or Java development. Many problems can be solved equally well by multiple patterns, which can lead to decision paralysis. |
Are there any alternatives? | You could write monolithic components that implement all the features required by an application, although this results in a project that is different to test and maintain. |
Problem | Solution | Listing |
|---|---|---|
Display content received from the parent component | Use the children prop | 8–9 |
Manipulate the components received via the children prop | Use the React.children prop | 10, 11 |
Enhance an existing component | Create a specialized component or a higher-order component | 12–18 |
Combine higher-order components | Chain the function calls together | 19, 20 |
Provide a component with the content it should render | Use a render prop | 21–24 |
Distribute data and functions without threading props | Use a context | 25–34 |
Consume a context without using a render prop | Use the simplified context API for class-based components and the useContext hook for functional components | 35, 36 |
Prevent errors from unmounting the application | Define an error boundary | 37–39 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 14-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
The content rendered by the App component displays the Message and ActionButton components and configures them so that clicking the button will update the counter state data value, which has been passed as a prop to the Message component.

Running the example application

The basic component relationship
This relationship is the foundation for React development and is the basic pattern used to arrange features in applications. This pattern is easy to understand in a simple example, its use in more complex situations can be less obvious, and it can be hard to know how to locate and distribute the state data, props, and callbacks without duplicating code and data.

A container component
The ThemeSelector component doesn’t add a lot of value at present, but you can see how it acts as a container for the content provided by the App component.
Name | Description |
|---|---|
React.Children.map | This method invokes a function for each child and returns an array of the function results. |
React.Children.forEach | This method invokes a function for each child without returning an array. |
React.Children.count | This method returns the number of children. |
React.Children.only | This method throws an array if the collection of children it receives contains more than one child. |
React.Children.toArray | This method returns an array of children, which can be used to reorder or remove elements. |
React.cloneElement | This method is used to duplicate a child element and allows new props to be added by the container. |
A component can’t manipulate the content it receives from the parent directly, so to provide the components received through the children prop with additional data or functions, the React.Children.map method is used in conjunction with the React.cloneElement method to duplicate the child components and assign additional props.
The cloneElement method accepts a child component and a props object, which is merged with the child component’s existing props.
One consequence of using the map method to enumerate the child components into an array is that React expects each component to have a key prop and will report a warning in the browser’s JavaScript console.

Adding props to contained components
Although a container doesn’t have any advanced knowledge of its children, the toArray method described in Table 14-3 can be used to convert the children to an array that can be manipulated using the standard JavaScript features, such as sorting or adding and removing items. This type of operation can also be performed on the result from the React.Children.map method, also described in Table 14-3, which returns an array as well.

Changing the order of child components in a container
Some components provide specialized versions of the features provided by another, more general, component. In some frameworks, specialization is handled by using features such as class inheritance, but React relies on the specialized component rendering the more general component and managing its behavior with props. To demonstrate, I added a file called GeneralList.js to the src folder and used it to define the component shown in Listing 14-12.
If you are used to class-based languages, such as C# or Java, you might expect to create a subclass using the same extends keyword that stateful components employ to inherit functionality from the React Component class. This is not how React is intended to be used, and you should compose components even though it can feel odd to do so at first.

General and more specialized components

Using higher-order components

A stateful higher-order component
The parent component provides the function for the render prop when it applies the component. In Listing 14-22, I have changed the App component so it provides the ProFeature component with the function it requires. (I have also removed some of the content for sake of brevity.)
The name of the prop that the parent uses to provide the function doesn’t have to be render, although that is the convention. You can use any name, just as long as it is applied consistently in both the parent and the child components.

Using a render prop
Render props are regular JavaScript functions, which means they can be invoked with arguments. This can be a useful feature in its own right, but it also helps understand how the context feature works, which I describe in the next section.

Using a render prop with an argument
The management of props can become difficult, regardless of how you choose to compose your application. As the complexity of the application increases, so does the number of components that need to cooperate. As the hierarchy of components grows, the state data gets lifted up higher in the application, further away from where that data is used, with the result that every component has to pass on props that it doesn’t use directly but that its descendants rely on.
To help avoid this problem, React provides the context feature, which allows state data to be passed from where it is defined to where it is needed without having to be relayed through the intermediate components. To demonstrate, I am going to make the Pro Mode in the example application more granular so that it disables the Sort button rather than hides the data list entirely.
In Listing 14-25, I have added a property to the button element rendered by the ActionButton component that sets the disabled property based on a prop and changes the Bootstrap theme to make it more obvious when the button is disabled.
The Redux package is often used for more complex projects and can be easier to use in large applications. See Chapters 19 and 20 for details.

Passing on props in the example application

Threading a prop through the application
It is this problem that the context feature solves, allowing state data to be passed directly to the component that uses it, without needing to be threaded through the intermediate components that separate them in the hierarchy.
The React.createContext method is used to create a new context and is provided with a data object that is used to specify the context’s default values, which are overridden when the context is used, which I demonstrate shortly. In the listing, the context that I defined is called ProModeContext, and it defines a proMode property, which will be false by default.
The component can still access the component’s state and prop data, which can be mixed freely with the data provided by the context. In this example, the callback prop is still used to handle click events, while the proMode context property is used to set the value of the className and disabled attributes.
The value property is used to provide the context with data values that override the defaults defined in Listing 14-28, which in this case is the proContextData state object.
Use the version of the setState method that accepts a function if you need to update a nested state property, as shown in Listing 14-28. See Chapter 11 for details of the different ways that setState can be used.

The effect of using a context to distribute a state data property
This component is a context consumer and uses the proMode property to set the value of a checkbox and invokes the toggleProMode function when it changes. The component also uses a prop to set the content of a label element, just to show that a component that consumes a context is still able to receive props from its parent. In Listing 14-33, I have updated the App component so that it uses the ProModeToggle component and provides the context with a function.
Avoid the temptation to create the object for a context in the provider’s render method, which can be appealing because it avoids the need to create nested state objects and to assign methods to state properties. Creating a new object each time the render method is called undermines the change detection process that React applies to contexts and can lead to additional updates.

Using multiple contexts
A static property named contextType is assigned the context, which is then available throughout the component as this.context. This is a relatively recent addition to React, but it can be easier to use, with the caveat that a component can consume only one context.
The useContext function returns a context object through which the properties and functions can be accessed.

The default error handling
Class-based components can implement the componentDidCatch lifecycle method, which is invoked when a child component throws an error. The React convention is to use dedicated error-handling components, known as error boundaries, that intercept errors and either recover the application so it can continue execution or display a message to the user to indicate the nature of the problem. I added a file called ErrorBoundary.js to the src folder and used it to define the error boundary shown in Listing 14-38.
Error boundaries apply only to errors that are thrown in lifecycle methods and do not respond to errors thrown in event handlers. Error boundaries also cannot be used for asynchronous HTTP requests and a try/catch block must be used instead, as shown in Part 3.
The componentDidCatch method receives the error object thrown by the problem component and an additional information object that provides the component’s stack trace, which can be useful for logging.

The effect of an error boundary
In this chapter, I described the different ways that components can be combined to compose applications, including containers, higher-order components, and render props. I also showed you how contexts can be used to distribute global data and avoid prop threading and how error boundaries can be used to handle problems in component lifecycle methods. In the next chapter, I describe the features that React provides for working with forms.
Question | Answer |
|---|---|
What are they? | Forms are the basic mechanism that allows applications to prompt the user for data. Validation is the process of checking that data to ensure it can be used by the application. |
Why are they useful? | Most applications require some degree of data entry from the user, such as e-mail addresses, payment details, or shipping addresses. Forms allow the user to enter that data, either in free-text form or by selecting from a range of predefined choices. Validation is used to ensure that the data is in a format that the application expects and can process. |
How are they used? | In this chapter, I describe controlled form elements, whose value is set using the value or checked props and whose change events are handled to process user editing or selection. These features are also used for validation. |
Are there any pitfalls or limitations? | There are differences in the way that different form elements behave and small deviations between React and the standard HTML form elements, as described in later sections. |
Are there any alternatives? | Applications do not have to use form elements at all. In some applications, uncontrolled form elements, where React is not responsible for managing the element’s data, may be a more suitable choice, as described in Chapter 16. |
Problem | Solution | Listing |
|---|---|---|
Add a form element to a component | Add the element to the content rendered by the component. Set the initial value of the element using the value prop and respond to changes using the onChange prop. | 1–10, 12, 13 |
Determine the state of a checkbox | Inspect the checked property of the target element when handling the change event | 11 |
Validate form data | Define validation rules and apply them when the user edits a field and triggers a change event | 14–25 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 15-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application
The simplest way to use form elements is to build on the React capabilities described in earlier chapters, using the state and event features. The result is known as a controlled component, and it will be familiar from earlier examples. In Listing 15-8, I have added an input element whose content is managed by React to the Editor component.
There is also an approach called an uncontrolled component, which I describe in Chapter 16.
The contents of the square brackets (the [ and ] characters) are evaluated to get the property name for the state update, which allows me to use the name property from the event.target object with the setState method. Not all types of form element can be processed in the same way, as you will see in later examples, but this approach reduces the number of event handling methods in a component.
Set the state property to the empty string ("") if you want to present an empty input element to the user. You can see examples of empty elements in Listing 15-8. Don’t use null or undefined because these values cause React to generate a warning in the browser’s JavaScript console.

Using a controlled component
Changes to the select element that presents a single item for selection can be handled using the same method defined for the input element since the selected value is accessed through the event.target.value property.

Using select elements

Using radio buttons to present a choice

Using a checkbox

Using checkboxes to populate an array

Using a text area element
Users will enter just about anything into form fields, either because they have made a mistake or because they are trying to skip through the form without filling it in, as noted in the sidebar. Validation checks the data that users provide to ensure that the application has data that it can work with. In the sections that follow, I show you how to perform form validation in a React application.
One reason that users will enter bad data into forms is they don’t regard the result as valuable. This can occur when the form interrupts a process that is important to the user with something that is unimportant, such as an intrusive prompt to create an account when reading an article or when the same form is presented at the start of a process that the user performs often.
Validation won’t help when the user doesn’t value the form because they will simply enter bad data that passes the checks but that is still bad data. If you find that your intrusive prompt for an e-mail address results in a lot of a@a.com responses, then you should consider that your users don’t think your weekly newsletter is as interesting as you do.
Use forms sparingly and only for processes that the user will regard as useful, such as providing a shipping address. For other forms, find an alternative way to solicit the data from the user that doesn’t interrupt their workflow and doesn’t annoy them each time they try to perform a task.
When validating forms, the different parts of the validation process can be distributed in a complex hierarchy of HTML and components. Instead of threading props to connect the different parts, I am going to use a context to keep track of validation problems. I added a file called ValidationContext.js to the src folder with the content shown in Listing 15-14. (Contexts are described in Chapter 14.)
The examples in this section rely on the validator package that was added to the project in Listing 15-2. If you skipped over the installation, you should go back and add the package before proceeding with the examples.
I am going to store the validation issues for each form element as an array and display messages for each of the issues alongside the element. The context provides access to a function that will return the validation messages for a specific field.
Name | Description |
|---|---|
isEmpty | This method returns true if a value is an empty string. |
isLength | This method returns true if a value exceeds a minimum length. |
isAlpha | This method returns true if a value contains only letters. |
isEmail | This method returns true if a value is a valid e-mail address. |
isEqual | This method returns true if two values are the same. |
The validation is performed in the getDerivedStateFromProps lifecycle method, which provides a component with a change to make changes to its state based on the props it receives. The component receives a data prop that contains the form data to be validated and a rules prop that defines the validation checks that should be applied and passes these to the ValidateData function defined in Listing 15-15. The result of the ValidateData function is assigned to the state.errors property and is an object with a property for each form field that has validation issues and an array of messages that should be presented to the user.
If the validation checks produce no errors, then the handleClick method invokes a function prop called submit and uses the validated data as the argument.
This component consumes the context provided by the FormValidator component and uses it to get the validation messages for a single form field whose name is specified through the field prop. This component doesn’t have any insight into the type of form element whose validation issues it reports or any knowledge of the overall validity of the form—it just requests the messages and displays them. If there are no messages to be displayed, then no content is rendered.

Validating form data
Notice that the validation features don’t deal directly with the input and textarea elements. Instead, the standard state and event features are used to bring the data under React’s control, where it is validated and dealt with by components that have no knowledge or interest in where the data came from. This means that once the basic validation features are in place, they can be different types of form element and different types of data. Each project has its own validation requirements, but the examples in the sections that follow demonstrate some of the most commonly required approaches that you can adapt to your own needs.

Validating a checkbox

Ensuring matching values
Some types of validation cannot be performed on individual values, such as ensuring that combinations of choices are consistent. This sort of validation can be performed only when the user has entered valid data into the form and submitted it, at which point an application can perform a final set of checks before processing the data.
In this chapter, I showed you how to create controlled components, which are form elements whose content is managed through a state property and whose editing is processed by an event handler. I showed you different types of form element and demonstrated how form data can be validated. Controlled form components are only one type that React supports, and in the next chapter, I introduce the refs feature and explained how uncontrolled form elements can be used.
Under normal circumstances, a component doesn’t interact directly with the elements in the Document Object Model (DOM). Normal interaction is through props and event handlers, which make it possible to compose applications and for components to work together without knowledge of the content they deal with.
There are some situations where components need to interact with the elements in the DOM, and React provides two features for this purpose. The refs feature—short for references—provides access to the HTML elements rendered by a component after they have been added to the DOM. The portals feature provides access to HTML elements outside of the application’s content.
Question | Answer |
|---|---|
What are they? | Refs are references to the elements in the DOM that have been rendered by a component. A portal allows content to be rendered outside of the application’s content. |
Why are they useful? | There are some features of HTML elements that cannot be easily managed without accessing the DOM directly, such as focusing an element. These features are also useful for integration with other frameworks and libraries. |
How are they used? | Refs are created using the special ref attribute and can be created using the React.createRef method or using a callback function. Portals are created using the ReactDOM.createPortal method. |
Are there any pitfalls or limitations? | These features are prone to misuse, such that they undermine component isolation and are used to duplicate features that are provided by React. |
Are there any alternatives? | Refs and portals are advanced features that will not be required in many projects. |
Problem | Solution | Listing |
|---|---|---|
Access the HTML element objects created for a component | Use a ref | 1–9, 11, 12, 18, 19 |
Use a form element without using state data and an event handler | Use uncontrolled form components | 10, 13–15 |
Prevent data loss during updates | Use the getSnapshotBeforeUpdate method | 16, 17 |
Access a child component’s content | Use the refs prop or ref forwarding | 20–23 |
Project content into a specific DOM element | Use a portal | 24–26 |
To create the example project for this chapter, open a new command prompt, navigate to a convenient location, and run the command shown in Listing 16-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
The Editor component renders a series of input elements whose value are set using state data properties and whose change events are handled by the handleChange method. There is a button element whose click event invokes the handleAdd method, which invokes a function prop using the state data, which is then reset.

Running the example application
Refs can be used when a component needs to access the DOM in order to use features of a specific HTML element. There are HTML features that cannot be achieved through the use of props, one of which is to ask an element to gain focus. The autoFocus attribute can be used to focus an element when content is first rendered, but the focus will switch to the button element once the user clicks it, which means that the user can’t start typing to create another item until they refocus, either by clicking the input element or by using the Tab key.
A ref can be used to access the DOM and invoke the focus method on the input element when the event triggered by clicking the Add button is handled, as shown in Listing 16-9.
Being able to access the DOM is a natural expectation for web developers, and refs can seem like a feature that makes React development easier, especially if you are coming to React from a framework like Angular.
It is easy to get carried away with refs and end up with a component that duplicates the content handling features that should be performed by React. A component that makes excessive use of refs is difficult to manage, can create dependencies on specific browser features, and can be difficult to run on different platforms.
Use refs only as a last resort, and always consider if you can achieve the same result using the state and props features.

Using a ref
The example application uses the controlled form components technique that I introduced in Chapter 15, where React is responsible for the contents of each form element, using a state data property to store its value and an event handler to respond to changes.
The input elements values are not required until the user clicks the Add button. In the handleAdd method, which is invoked when the button is clicked, the refs for each of the input elements is used to read the value property. The result has the same appearance to the user as earlier examples, but behind the scenes, React is no longer responsible for managing the element values or responding to change events.
React isn’t responsible for uncontrolled elements, but it can still provide an initial value, which is then managed by the browser. To set the value, use the defaultValue or defaultChecked attribute, but bear in mind that the value you specify will be used only when the element is first rendered and won’t update the element when it is changed.
The value of the ref property of the input elements is set to a method, which is invoked when the content is rendered. Instead of dealing with a ref object, the specified method receives the HTMLElement object directly, instead of a reference object with a current property. In the listing, the setElement method receives the elements, which are added to the formElements object using the name value so that I can differentiate between the elements.
The input elements are generated using the properties of the formElements object, where each property is assigned an object with label and name properties that are used in the render method to configure the element.

Programmatically creating form elements and refs
The valueMissing property will be true when I have specified that the element must have a value but is empty. The tooShort property will be true when there are fewer characters in the element’s value than specified by the validation rules. The rangeUnderflow property will be true for numeric values that are smaller than a specified minimum value.
The GetValidationMessages function receives an HTML element object and asks the browser for data validation by calling the element’s checkValidity method. The checkValidity method returns true if the element’s value is valid and false otherwise. If the element’s value isn’t valid, then the element’s validity property is checked for the valueMissing, tooShort, and rangeUnderflow properties with true values and used to create an array of errors that can be shown to the user.
The HTML validation features include a wider range of validation checks and validity properties than I use in this chapter. See https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation for a good description of the available features.

Validating an element

Validating all elements
Refs are not assigned a value until React invokes a component’s render method. If you are using the createRef method, the current property will not be assigned a value before the component has rendered its content. Similarly, callback refs won’t invoke their method until the component has rendered.
The assignment of refs may seem late in the component lifecycle, but refs provide access to DOM elements, which are not created until the rendering phase, which means that React hasn’t created the elements that refs refer to until the render method is invoked. The element associated with a ref can be accessed only in the componentDidMount and componentDidUpdate lifecycle methods because they occur after rendering has been completed and the DOM has been populated or updated.

Replacing elements
The input element into which you entered text has been destroyed, and its content has been lost. To make matters more confusing for the user, any validation errors that have been detected are part of the component’s state data, which means they will be displayed alongside the new input element, even though the data value they describe is no longer visible.

The snapshot process
This getSnapshotBeforeUpdate method allows a component to inspect its current content and generate a custom snapshot object before the render method is called. Once the update is complete, the componentDidUpdate method is called and provided with the snapshot object so that the component can modify the elements that are now in the DOM.
A snapshot doesn’t help preserve context if the component is unmounted and re-created, which can happen when an ancestor’s content changes. In these situations, the componentWillUnmount method can be used to access refs, and the data can be preserved via a context, as described in Chapter 15.
The getSnapshotBeforeUpdate method receives the component’s props and state as they were before the update was triggered and returns an object that will be passed to the componentDidUpdate method after the update. In the example, I don’t need to access props or state because the data I need to preserve is contained in the input elements. React doesn’t mandate a specific format for the snapshot object, and the getSnapshotBeforeUpdate method can return data in any format that will be useful. In the example, the getSnapshotBeforeUpdate method returns an array of objects with name and value properties.

Using snapshot data
The getSnapshotBeforeUpdate and componentDidUpdate methods are called for every update, even when React hasn’t replaced the component’s elements in the DOM, which is why I apply a snapshot value only when an element’s value differs from the snapshot value when the update has been completed.
There is an unintended consequence of using the HTML5 constraint validation API in the previous example. Validation is performed only when the user edits the contents of the text field and not when the value is set programmatically. When I use the snapshot data to set the value of a newly created input element, it will pass validation, even if the value previously failed validation. The effect is that the user can bypass validation by entering bad values into the name or category input elements, checking the wrap content checkbox, and clicking the Add button.
This is a problem that can be worked around, but the underlying issue is that using refs to access the DOM directly presents a series of small conflicts, each of which can be solved with the addition of a few lines of code. But these fixes often present other issues or compromises that require additional work, and the result is a fragile application made from complex components.
Working directly with the DOM can be essential in some projects, and there can be advantages to avoiding duplicating data and features that are already in the DOM. But use refs only when they are required because they can create as many problems as they solve.
Some projects are moved to React gradually so that components have to interoperate with existing features that are written in another library or framework. The most common example is jQuery, which was the most popular choice for web application development before the era of frameworks like React and Angular and which is still widely used for simple projects. If you have an extensive set of features that are written in jQuery, for example, then you can apply them to the HTML elements rendered by a component using refs. To demonstrate, I am going to use jQuery to assign form elements with invalid elements to a class that will apply a Bootstrap style. I added a file called jQueryColorizer.js to the src folder and added the code shown in Listing 16-18.
This example requires the jQuery package that was added to the project in Listing 16-3. If you did not install jQuery, you should do so before proceeding.
The jQuery statement locates all the input elements that are assigned to the invalid pseudoclass and adds them to the border-danger class and adds any input elements in the valid pseudoclass to the border-success class. The valid and invalid classes are used by the HTML constraint validation API to indicate an element’s validation status. In Listing 16-19, I have added a ref and used it to invoke the jQuery function from the App component.
Using refs to incorporate other frameworks is difficult and prone to problems. Like any use of refs, it should be done with caution and only when you are unable to rewrite the functionality in React. You may feel that you will save time by building on your existing code, but my experience is that any time saved will be spent trying to work around a long series of small problems that arise because the two frameworks work in different ways.
If you have to use another library or framework alongside React, then you should pay close attention to the way that the frameworks approach the DOM. You will find that React and the other framework expect to have complete control of the content they create, and unexpected results can arise when elements are added, removed, or changed in a way that the framework developers did not expect.

Providing jQuery with an element via a ref
In Listing 16-19, I added a div element around the Editor element. When React renders the content into the DOM, the Editor element won’t be part of the HTML document, and adding the div element ensures that jQuery is able to access the application’s content.
Refs do work with components, and if I had applied the ref prop to the Editor element, the value of the ref’s current property will be assigned to the Editor object that React created when rendering the App component’s content.
A ref to a component allows access to that component’s state data and methods. It can be tempting to use refs to invoke a child component’s methods because it produces a development experience that more closely resembles the way that objects are conventionally used.
Manipulating a component via a ref is bad practice. It produces tightly coupled components that end up working against React. The state data, props, and event features may feel less natural at first, but you will become accustomed to them, and the result is an application that takes full advantage of React and that is easier to write, test, and maintain.
The refs prop is given special handling by React, which means that care must be taken when a component requires a ref to a DOM element rendered by one of its descendants. The simplest approach is to pass the ref object or callback function using a different name, in which case React will pass along the ref as it would any other prop. To demonstrate, I added a file called FormField.js to the src folder and used it to define the component shown in Listing 16-20.
Accessing a child component’s content should be done with caution because it creates tightly coupled components that are harder to write and test. Where possible, you should use props to communicate between components.

Accessing a child’s content
This example produces the same effect as shown in Figure 16-10, with the advantage that the App component doesn’t require any special knowledge of how the ref is handled inside the child component.

Adding an Element to the HTML Document
The PortalWrapper component is defined using the props.children property to create a container but returns its content using the ReactDOM.createPortal method, whose arguments are the content to render and the DOM target element. In this example, I use the DOM API’s getElementById method to locate the target element added to the HTML file in Listing 16-24. In Listing 16-26, I have used the portal in the App component.
You cannot use a portal to render content to an element using a ref. Portals are used during the rendering process, and refs are not assigned elements until rendering is complete, which means that you won’t be able to access an element via a ref early enough in the lifecycle for the ReactDOM.createPortal method. Use contexts, as described in Chapter 14, if you need coordination between components in different parts of the application or use one of the packages described in Part 3.

Using a portal
In this chapter, I described the React features for working directly with the DOM. I explained how refs can provide access to content rendered by a component and how this makes uncontrolled form elements possible. I also demonstrated a portal, which allows content to be rendered outside of the application’s component hierarchy. These features can be invaluable but should be used sparingly because they undermine the normal React development model and result in closely coupled components. In the next chapter, I show you how to perform unit testing on React components.
Question | Answer |
|---|---|
What is it? | React components require special support for testing so that their interactions with other parts of the application can be isolated and inspected. |
Why is it useful? | Isolated unit tests are able to assess the basic logic provided by a component without being influenced by the interactions with the rest of the application. |
How is it used? | Projects created with create-react-app are configured with basic test tools that are supplemented with packages that simplify the process of working with components. |
Are there any pitfalls or limitations? | Effective unit testing can be difficult, and it can take time and effort to get to the point where unit tests are easily written and run and you are sure that you have isolated the correct part of the application for testing. |
Are there any alternatives? | Unit testing is not a requirement and is not adopted in all projects. |
Unit testing is a contentious topic. This chapter assumes you do want to do unit testing and shows you how to set up the tools and apply them to a React application. It isn’t an introduction to unit testing, and I make no effort to persuade skeptical readers that unit testing is worthwhile. If would like an introduction to unit testing, then there is a good article here: https://en.wikipedia.org/wiki/Unit_testing .
I like unit testing, and I use it in my own projects—but not all of them and not as consistently as you might expect. I tend to focus on writing unit tests for features and functions that I know will be hard to write and that are likely to be the source of bugs in deployment. In these situations, unit testing helps structure my thoughts about how to best implement what I need. I find that just thinking about what I need to test helps produce ideas about potential problems, and that’s before I start dealing with actual bugs and defects.
That said, unit testing is a tool and not a religion, and only you know how much testing you require. If you don’t find unit testing useful or if you have a different methodology that suits you better, then don’t feel you need to unit test just because it is fashionable. (However, if you don’t have a better methodology and you are not testing at all, then you are probably letting users find your bugs, which is rarely ideal.)
Problem | Solution | Listing |
|---|---|---|
Perform unit tests on React components | Use Jest (or one of the other test frameworks available) along with Enzyme to create the tests | 9–11 |
Isolate a component for testing | Test using shallow rendering | 12 |
Test a component along with its descendants | Test using full rendering | 13 |
Test a component’s behavior | Test using the Enzyme features for working with props, state, methods, and events | 14–17 |
For this chapter, I am going to use a new project. Open a new command prompt, navigate to a convenient location, and run the command shown in Listing 17-1 to create a project called testapp.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Name | Description |
|---|---|
enzyme | Enzyme is a test package created by Airbnb that makes it easy to test components by exploring the content they render and examining their props and state. |
enzyme-adapter-react-16 | Enzyme requires an adapter for the specific version of React being used. This package is for the version of React used throughout this book. |
App creates three ValueInput components and configures them so that the values the user enters are stored in the fieldValues state array. A button is configured so that a click event invokes the updateTotal method, which sums the values from the ValueInput components and updates a state data value that is displayed by the Result component.

Running the example application
When you save the change, the test will run again and will pass this time.
Shallow rendering isolates a component from its children, allowing it to be tested on its own. It is an effective technique for testing the basic functions of a component without the effects caused by interaction with its content. To test the App component using shallow rendering, I added a file called appContent.test.js to the src folder and added the code shown in Listing 17-12.
Jest will find tests in files whose name ends with test.js or spec.js or any file in a folder named __tests__ (two underscores before and after tests).
This is the first real unit test in this chapter, so I will explain each part and show you how they fit together.
The Enzyme.configure method is passed a configuration object whose adapter property is assigned the imported contents of the adapter package. If you need to test a different version of React, you can see the list of adapters available at https://airbnb.io/enzyme .
The first argument should be a meaningful description of what the test aims to establish. In this case, the test checks that App renders three ValueInput components.
Name | Description |
|---|---|
find(selector) | This method finds all elements matched by the CSS selector, which will match element types, attributes, and classes. |
findWhere(predicate) | This method finds all elements that are matched by the specified predicate. |
first(selector) | Returns the first element that is matched by the selector. If the selector is omitted, then the first element of any type will be returned. |
children() | Creates a new selection containing the children of the current element. |
hasClass(class) | This method returns true if an element is a member of a specified class. |
text() | This method returns the text content from an element. |
html() | This method returns the deep rendered content from the component so that all of the descendant components are processed. |
debug() | This method returns the shallow rendered content from the component. |
Name | Description |
|---|---|
toBe(value) | This method asserts that a result is the same as the specified value (but need not be the same object). |
toEqual(object) | This method asserts that a result is the same object as the specified value. |
toMatch(regexp) | This method asserts that a result matches the specified regular expression. |
toBeDefined() | This method asserts that the result has been defined. |
toBeUndefined() | This method asserts that the result has not been defined. |
toBeNull() | This method asserts that the result is null. |
toBeTruthy() | This method asserts that the result is truthy. |
toBeFalsy() | This method asserts that the result is falsy. |
toContain(substring) | This method asserts that the result contains the specified substring. |
toBeLessThan(value) | This method asserts that the result is less than the specified value. |
toBeGreaterThan(value) | This method asserts that the result is more than the specified value. |
Jest keeps track of which matches fail and reports the outcome when all the tests in the project have been run. The matcher in Listing 17-12 checks that there are three ValueInput components in the content rendered by App.
There are now two tests in the project, and both of them are run. You can leave the tests to run automatically, or you can run one or more tests on demand using the options that are shown when the W key is pressed.
The first new test uses the Enzyme mount function to fully render App and its descendants. The wrapper returned by mount supports the methods described in Table 17-5, and the full set of features is described at https://airbnb.io/enzyme/docs/api/mount.html . I use the find method to locate input elements that have been assigned to the form-control class and use expect to make sure that there are three of them. The second new test locates the same elements but does so using shallow rendering and checks that there are no input elements in the content.
Name | Description |
|---|---|
instance() | This method returns the component object so that its methods can be invoked. |
prop(key) | This method returns the value of the specified prop. |
props() | This method returns all of the component’s props. |
setProps(props) | This method is used to specify new props, which are merged with the component’s existing props before it is updated. |
state(key) | This method is used to get a specified state value. If no value is specified, then all of the component’s state data is returned. |
setState(state) | This method changes the component’s state data and then re-renders the component. |
simulate(event, args) | This method dispatches an event to the component. |
update() | This method forces the component to re-render its content. |
The App component is configured with a title prop when it is passed to the shallow method. The test checks that the prop is used to override the default value by locating the h5 element and getting its text content and also by reading the value of the title state property. The test passes only if both the contents of the h5 element and the state property are the same as the value of the title prop.
The new test shallow renders an App component and then calls the updateFieldValue method with an array of values before then invoking the updateTotal method. The state method is used to get the value of the total state property, which is compared to the sum of the values passed to the updateFieldValue method.
The new test simulates the click event, the handler for which invokes the component’s updateTotal method. To ensure that the event has been handled, the value of the total state data property is read.
The new test locates the input element rendered by the first ValueInput and triggers its change event, supplying an argument that will provide the component’s handler with the values it needs. The instance method is used to invoke the updateTotal method of the App component, and the state method is used to check that the state data for both the App and ValueInput components has been updated correctly.
In this chapter, I showed you how to perform unit tests on React components. I showed you how to run tests using Jest and how to perform those tests with shallow and full rendering, provided by the Enzyme package. I explained how to examine the content rendered by a component, how to invoke its methods, how to explore its state, and how to manage its props. Together, these features allow a component to be tested in isolation and in combination with its children. In the next part of the book, I describe how to supplement the core React features to create complete web applications.
React provides an excellent set of features for presenting HTML content to the user and relies on third-party packages to provide the supporting functionality required to develop complete web applications. There are countless packages available for use with React, and in this part of the book, I introduce those that are most widely used and most likely to be needed by readers of this book. These packages are all open-source and freely available, and there are paid-for support options in some cases.
Name | Description |
|---|---|
Redux | Redux provides a data store that manages data outside of an application’s components. I use this package in Chapters 19 and 20. |
React Redux | React Redux connects React components through its props to a Redux data store, allowing direct access to data without relying on prop threading. I use this package in Chapters 19 and 20. |
React Router | React Router provides URL routing for React applications, allowing the components displayed to the user to be selected based on the browser’s URL. I use this package in Chapters 21 and 22. |
Axios | Axios provides a consistent API for making asynchronous HTTP requests. I use this package in Chapter 23 to consume a RESTful web service and in Chapter 25 to consume a GraphQL service. |
Apollo Boost | Apollo is a client for consuming GraphQL services, which are more flexible than traditional RESTful web services. I use the Boost edition of this package, which provides sensible defaults for React applications, in Chapter 25 to consume a GraphQL service. |
React Apollo | React Apollo connects React components to GraphQL queries and mutations, allowing a GraphQL service to be consumed through props. |
There are credible alternatives for each of the packages I have selected, and I make suggestions in each chapter in case you can’t get along with the packages that are covered. Please e-mail me at adam@adam-freeman.com if there is a package that interests you that I have not covered in this part of the book. Although I make no promises, I will try to include commonly requested packages in the next edition of this book or, if there is sufficient demand, in updates posted to this book’s GitHub repository.
Open a new command prompt, navigate to a convenient location, and run the command shown in Listing 18-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application

The example application
Example applications are contrived, of course, and my goal, in this case, is to show that the core React features are powerful but are not sufficient on their own to create complex web applications. Once the application has been defined, I highlight the problems that it contains, each of which I address using the tools and packages described in the following chapters.
This component renders a single row in a table, with columns for id, name, category, and price properties, which are obtained from a prop object called product. There is a further column that displays Edit and Delete buttons that invoke function props named editCallback and deleteCallback, passing the product prop as an argument.
This component renders a table, whose body is populated with ProductTableRow components for each object in an array prop named products. This component passes on the deleteCallback and editCallback function props to the ProductTableRow instances.
The ProductEditor component presents the user with fields for editing the properties of an object. The initial values for the fields are received from a prop named product and used to populate state data. There is a Save button that invokes a function prop named saveCallback when it is clicked, passing the state data values so that can be saved. There is also a Cancel button that invokes a function callback named cancelCallback when it is clicked.
This component defines state data to determine whether the data table or the editor should be shown and, if it is the editor, which product the user wants to modify. This component passes on function props to both the ProductEditor and ProductTable components, as well as introducing its own functionality.
This component renders a table row with the id, name, city, and products properties of a prop object named supplier. There are also Edit and Delete buttons that invoke function props.
This component renders a table, mapping each object in the suppliers prop array into a SupplierTableRow. The props for the callbacks are received from the parent component and passed on.
The SupplierDisplay component has its own state data for determining whether the editor or table component should be displayed.
The component defines product and suppliers state data properties and defines methods that allow objects to be deleted or saved for each data category. The component renders a Selector and provides the category display components as its children.

Testing the example application
The example application shows how React components can be combined to create applications—but it also shows the limitations of the features that React provides.
The biggest limitation of the example application is that it uses statically defined data that is hard-coded into the App component. The same data is displayed each time the application is started, and changes are lost when the browser is reloaded or closed.
The most common way of persisting data outside of a web application is to use a web service, although modern browsers provide support for storing limited amounts of data locally. React doesn’t include integrated support for working with web services, but there are some good choices, both for simple web services, which I describe in Chapter 23, and those that present more complex data, which I describe in Chapters 24 and 25.
The next limitation is that the state data has been lifted all the way to the top of the application. As I explained in Part 2, state data can be used to coordinate between components, and that state data can be lifted up to the common ancestor of components that need to access the same data.
The example application shows the downside of this approach, such that the important data—the products and suppliers arrays, in this case—end up being pushed to the top level of the application. React destroys components when they are unmounted and their state data is lost, which means that any component that is below the Selector in the example application is unsuitable for storing the application’s data. As a result, all of the application’s data has been defined in the App component, along with the methods that operate on that data. I exacerbated this problem with the structure I chose for the application, but the underlying issue is that a component’s state is perfect for keeping track of the data required to manage the content presented to the user—such as whether a data table or an editor should be displayed—but isn’t well-suited for managing the data that relates to the purpose of the application, often known as the domain data or model data.
The best way to prevent the model data from being pushed up to the top-level component is to put it in a separate data store, which leaves the React components to deal with the presentation of the data without having to manage it. I explain the use of a data store and show you how to create one in Chapters 19 and 20.
The application is also limited in the way that it requires the user to work through a specific sequence of tasks to get to specific features. In many applications, especially those designed to support a specific corporate function, users have to perform a small set of tasks and want to be able to start them as easily as possible. The example application only presents its features in response to clicking particular elements. In Chapters 21 and 22, I add support for URL routing, which makes it possible for users to navigate to specific features directly.
In this chapter, I created the example application that I will enhance throughout this part of the book. In the next chapter, I start that process by introducing a data store, which will allow the model data to be removed from the App component and distributed directly to the parts of the application that need it.
A data store moves the application’s data outside of the React component hierarchy. Using a data store means that the data doesn’t have to be lifted up to the top-level component and doesn’t have to thread props to ensure access to that data where it is needed. The result is a more natural application structure, which leaves the React components to focus on what they are good at, which is rendering content for the user.
Question | Answer |
|---|---|
What is it? | A data store moves an application’s data outside of the component hierarchy, which means that data doesn’t have to be lifted up and then made available to descendants through prop threading. |
Why is it useful? | Data stores can simplify the components in a project, producing an application that is easier to develop and test. |
How is it used? | Data is moved into a dedicated part of the application that can be accessed directly by the components that require it. In the case of Redux, components are connected to the data store through props, which takes advantage of the nature of React, although the mapping process itself can be awkward and require close attention. |
Are there any pitfalls or limitations? | Data stores can be complex and often work in counterintuitive ways. Some data store packages, including Redux, enforce specific methods of dealing with data that some developers find restrictive. |
Are there any alternatives? | Not all applications need a data store. For smaller amounts of data, using component state features may be acceptable and the React context API, described in Chapter 14, can be used for basic data management features. |
Problem | Solution | Listing |
|---|---|---|
Create a data store | Define the initial data, action types, creators, and reducers | 3–8, 13–21 |
Add a data store to a React application | Use the Provider component from the React-Redux package | 9 |
Consume a data store in a React component | Use the connect function to map the component’s props to the data store’s data and action creators | 10, 12 |
Dispatch multiple data store actions | Use the dispatch function directly when mapping data store action creators to component function props. | 22 |
In this chapter, I continue using the productapp project created in Chapter 18. To prepare for this chapter, open a new command prompt and run the commands shown in Listing 19-1 in the productapp folder.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Name | Description |
|---|---|
redux | This package contains the main Redux data store features. |
react-redux | This package contains the integration features for using Redux with React. |

Running the example application
Much like React, Redux imposes a specific flow for data and changes. And, like React, understanding how the different parts of Redux fit together can be difficult at first. There are two characteristics of Redux that cause confusion.
First, changes in Redux are not applied directly to the data in the store, even though that data is expressed as regular JavaScript objects. Instead, Redux relies on functions that accept a payload and update the data in the store, similar to the way that React components enforce the use of the setState method to update state data.
Name | Description |
|---|---|
action | An action describes an operation that will change the data in the store. Redux doesn’t allow data to be modified directly and requires actions to specify changes. |
action type | Actions are plain JavaScript objects that have a type parameter, which specifies the action type. This ensures that actions can be identified and processed correctly. |
action creator | An action creator is a function that creates an action. Action creators are presented to React components as function props so that invoking the action creator function applies a change to the data store. |
reducer | A reducer is a function that receives an action and processes the change it represents in the data store. An action specifies which operation should be applied to the data store, but it is the reducer that contains the JavaScript code that makes it happen. |
selector | A selector provides a component with access to the data it requires from the data store. Selectors are presented to React components as data props. |
Redux is only one of the data store packages available for use with React, although it is the most well-known and the one that is chosen by most projects. If you don’t like the way that Redux works, then MobX ( https://github.com/mobxjs/mobx ) may be a good alternative. MobX works well with React and allows direct state changes. The main drawback is that it relies on decorators, which some developers find awkward and which are not yet part of the JavaScript specification (although they are widely used, including by Angular).
In Chapters 24 and 25, I introduce GraphQL and explain its use in retrieving data for applications. If you become a committed React user, then you may want to consider Relay ( https://facebook.github.io/relay ) for data management. Relay works only with GraphQL, which means that it isn’t suitable for all projects, but it has some interesting features and integrates well with React.
The example application contains similar sets of features applied to two types of data. In this situation, it is easy to end up with duplication in the code that manages the data store, performing essentially the same operation but on different collections of objects, with the effect that the data store is harder to write, harder to understand, and prone to errors introduced by copying the code for one type of data and incorrectly adapting it.
In later chapters, I show you how to get data from web services, but for the moment I am going to continue using statically defined data. To define the initial contents of the data store, I created a file called initialData.js in the store folder and added the statements shown in Listing 19-4.
As I add more features to the example application, I am going to create different sections of the data store to keep features separate. I am going to refer to the product and supplier data presented to the user as model data to differentiate it from the internal data used to coordinate between components, which I will refer to as state data.
The initial state of the data store is defined as a regular JavaScript object; one of the characteristics of working with Redux is that it relies on pure JavaScript for many of its features. To make it clear when the data store is being used, I have used different details for the objects in the PRODUCTS and SUPPLIERS arrays.
To provide the functionality for the example application, I need three events: STORE to add objects to the data store, UPDATE to modify existing objects, and DELETE to remove objects.
The value assigned to the action types isn’t important just as long as it is unique, and the simplest approach is to assign each action type a string value of its name.
Actions are objects that are sent from the application to the data store to request a change. An action has an action type and a data payload, where the action type specifies the operation and the payload provides the data that the operation requires. Actions are ordinary JavaScript objects that can define any combination of properties required to describe an operation. The convention is to define a type property to indicate the event type, and I will supplement this with dataType and payload properties to specify the data that the action should be applied to and the data required for the action.
There are four action creators in the listing. The saveProduct and saveSupplier functions receive an object parameter and pass it to createSaveEvent, which inspects the value of the id property to determine whether a STORE or UPDATE action is required. The deleteProduct and deleteSupplier action creators are simpler and create a DELETE action whose payload is the id property value of the object to be deleted.
The reducer receives the current data from the data store and an action as its parameters. It inspects the action and uses it to create a new data object, which will replace the existing data in the data store.
This ensures that all the properties are copied to the result object. The property for the data that is changed is then replaced with the data modified by the action.
Redux will report an error if the function returns undefined, and it is important to ensure that you return a useful result. In the listing, I return the initialData object that was defined in Listing 19-4.
When the new data store object is created, JavaScript will evaluate the action.dataType property and use its value to define a new property on the object and access the property on the old data store, using the values I defined in Listing 19-5, so that a dataType value of PRODUCTS selects the products data and a value of SUPPLIERS selects the supplier data. You don’t have to use this type of technique in your own projects, but it helps keep the code concise and manageable.
Redux provides the createStore function, which creates the data store and prepares it for use. I added a file called index.js to the store folder and added the code shown in Listing 19-8.
You don’t have to use the index.js file name, but doing so allows the data store to be imported using only the name of the folder, as shown in Listing 19-9.
The default export from the index.js file is the result of calling createStore, which accepts the reducer function as its argument. I also exported the action creators so that all of the data store’s functionality can be accessed through a single import statement elsewhere in the application, which makes using the data store a little simpler.
The actions, reducers, and selectors I created in the previous section are not yet integrated into the application, and there are no links between the components in the application and the data in the data store. In the sections that follow, I show you how to use the data store to replace the state data and methods that currently manage the application data.
The Provider component has a store prop that is used to specify the data store, which I assigned the name dataStore in the import statement.
This function is conventionally named mapStateToProps, and it returns an object that maps prop names for the connected component to data in the store. These mappings are known as selectors because they select the data that will be mapped to the component’s prop. In this case, selector maps the store’s products array to a prop named products.
The React-Redux package supports different ways of connecting action creators to function props, but this is the simplest, which is to create an object that maps prop names to action creator functions. When the component is connected to the data store, the action creator functions defined in this object will be wired up so that the reducer is automatically invoked. In this case, I mapped the saveProduct and deleteProduct action creators to function props named saveCallback and deleteCallback.
The connect function creates a higher-order component (HOC) that passes on props connected to the data store merged with the props that are provided by the parent component.
Higher-order components are described in Chapter 14.

Using a data store for product data
Because the props provided by the data store replace those from the parent component, the ProductDisplay component operates entirely on the data store data, including creating, editing, and deleting objects.

Using a data store for supplier data
Notice I don’t have to provide props for the ProductDisplay and SupplierDisplay components to give them access to data and methods; these will be set up by the connect method that connects the components to the data store.
Data stores are not just for the data that is displayed to the user—they can also be used to store the state data that is used to coordinate and manage components. Expanding the data store to include state data will allow me to connect the model data in the store directly to the components that use it, which is not possible currently because ProductDisplay and SupplierDisplay maintain state data that is used to select the content presented to the user.
In the sections that follow, I move the state data and code that manages it into the data store so that I can further simplify the application.
I want to keep the state data separate from the model data, so I am going to add some structure to the store. I like to represent the structure in the initial data that I used to populate the data store, although this is entirely to help me understand the shape of the data that I am working with and is not a requirement enforced by Redux.
My goal is to move the state data and logic in the ProductDisplay and SupplierDisplay components into the data store. These components track the user’s selection for editing and whether the table or the editor component should be rendered. To provide this information in the store, I defined editing, selected and selectedType properties in the stateData section.
The action creators correspond to the methods defined by the ProductDisplay and SupplierDisplay components and allow a user to start editing an object, cancel editing, and start creating a new object.
The reducer for the state data keeps track of what the user is editing or creating, which echoes the approach taken by the existing components in the example application, although I am going to use a single set of properties to coordinate the editors for both types of model data in the application.
The argument for the createReducers function is an object whose property names correspond to sections of the data store and the reducers that will manage them. In the listing, I have made the original reducer responsible for the modelData section of the data store and have made the reducer defined in Listing 19-15 responsible for the stateData section. The combined reducers are passed to the createStore function to create the data store.
Each reducer operates on a separate part of the data store, but when an action is processed, each reducer is passed the action until one of them returns a new data store object, indicating that the action has been processed.
When the combineReducers function is used, each reducer is provided with only its section of the data in the store and is unaware of the rest of the data and the other reducers. This means I only need to change the source of the initial data and don’t have to worry about navigating through the new data structure when applying an action.
Now that the state data has been put into the data store, I can connect it to components. Rather than configure each component separately, I am going to define separate connector components that will take care of mapping data store features to component props. I created a file called EditorConnector.js in the src/store folder with the code shown in Listing 19-18.
A common approach when using a data store is to use two different types of component. Presenter components are responsible for rendering content to the user and responding to user input. They receive data and function props but are not directly connected to the data store. Connector components—confusingly, also known as container components—exist to connect to the data store to provide presenter components with props. This is the general approach I have taken in this part of the chapter, although, as with much in the React/Redux world, implementation details can vary, and there is disagreement over how best to approach this kind of separation.
The EditorConnector is a higher-order component that provides a presentation component with the props required by both the ProductEditor and SupplierEditor components, which means that these components can be connected to the data store using the same code, rather than requiring separate uses of the connect function. To support both types of editor, the HOC function accepts a data type that is used to select the data and action creators that will be mapped to props.
Notice that the segmentation of the data store created by the combineReducers function doesn’t have any effect on data selection, which means I can select data from the entire store.
The number of commented-out statements shows the amount of the ProductDisplay component that was dedicated to providing data and function props to its children, all of which is now handled through the data store and the connector components. There is no longer any need for local state data, so the constructor and all of the methods except render can be removed. The component does still require a connection to the data store, however, because it needs to know which child component to display and needs to generate key values for the editor components.
As I have pushed the use of the data store further into the component hierarchy, the differences between the components for product and supplier data have been reduced, and these components are converging. At this point, I could replace the ProductDisplay and SupplierDisplay components with a single component that deals with both data types and keep working toward driving the entire application from the data store. In practice, however, there comes a point where convergence no longer simplifies the application and starts simply moving complexity around. As you gain experience working with the data store, you will find the point where you are comfortable with the degree you rely on the data store and the amount of duplication in the components. Like much of React and Redux development, this is as much personal preference as it is good practice, and it is worth experimenting until you find an approach that suits you.

Making a change using the example application
The problem is that the connect function that maps action creators to props allows for only one action creator to be selected by default, but I need two action creators to solve this problem: the saveProduct or saveSupplier creators to update the model data and the endEditing creator to signal that editing is complete and the table should be presented to the user.
I can’t define a new creator to perform both tasks because each action is handled by a single reducer and each reducer is responsible for an isolated part of the data in the store, which means that an action can lead to a change in the model data or the state data but not both.

Dispatching multiple actions

Altering data in a selector
Transforming data in a selector ensures consistency whenever the same view of the data is required, but it does mean that the connected component is no longer working with the original data from the data store. As a consequence, relying on the data received by one component to drive the behavior of another component can lead to problems, and it is for this reason that I used ID values to keep track of the objects that are selected by the user for editing.
In this chapter, I created a Redux data store and connected it to the components in the example application. I showed you how to define actions, action creators, reducers, and selectors, and I demonstrated how data store features can be presented to components as props. In the next chapter, I describe the advanced features Redux provides through its API.
Question | Answer |
|---|---|
What are they? | The Redux and React-Redux packages both define APIs that support advanced use, going beyond the basic techniques described in Chapter 19. |
Why are they useful? | These APIs are useful for exploring how data stores work and how components can be connected to them. They can also be used to add features to a data store and to fine-tune an application’s use of it. |
How are they used? | The Redux API is used directly on the data store object or during its creation. The React-Redux API is used when connecting a component to the data store, either using the connect function or using its more flexible connectAdvanced alternative. |
Are there any pitfalls or limitations? | The APIs described in this chapter require careful thought to ensure that you achieve the desired effect. It is easy to create an application that doesn’t properly respond to data store changes or that updates too often. |
Are there any alternatives? | You don’t have to use the APIs described in this chapter, and most projects will be able to make effective use of a data store using only the basic techniques described in Chapter 19. |
Problem | Solution | Listing |
|---|---|---|
Access the Redux data store API | Use the methods defined by the data store object returned by the createStore method | 2–4 |
Observe data store changes | Use the subscribe method | 5 |
Dispatch actions | Use the dispatch method | 6 |
Create a custom connector | Map the props of a component to the data store features | 7–8 |
Add features to the data store | Create a reducer enhancer | 9–11 |
Process actions before they are passed to the reducer | Create a middleware function | 12–16 |
Extend the data store API | Create an enhancer function | 17–19 |
Incorporate a component’s props into a data store mapping | Use the optional argument to the connect function | 20–24 |
In this chapter, I continue working with the productapp project created in Chapter 18 and modified in Chapter 19. No changes are required for this chapter. Open a new command prompt, navigate to the productapp folder, and run the command shown in Listing 20-1 to start the development tools.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application
In most React applications, access to a Redux data store is mediated through the React-Redux package, which maps data store features to props. This is the most convenient way to use Redux, but there is also a full API that provides direct access to data store features, which I describe in the sections that follow, starting with the features that provide access to the data in the store.
Name | Description |
|---|---|
getState() | This method returns the data from the data store, as described in the “Obtaining the Data Store State” section. |
subscribe(listener) | This method registers a function that will be invoked each time changes are made to the data store, as described in the “Observing Data Store Changes” section. |
dispatch(action) | This method accepts an action, typically produced by an action creator, and sends it to the data store so that it can be processed by the reducer, as described in the “Dispatching Actions” section. |
replaceReducer(next) | This method replaces the reducer used by the data store to process actions. This method is not useful in most project, and middleware provides a more useful mechanism for changing the behavior of the data store. |

Getting the contents of the data store
If you examine the data that has been obtained through the getState method, you will see that everything is included so that both the contents of the modelData and stateData properties are available. The segmentation that is applied to reducers doesn’t affect the data returned by the getState method, which provides access to everything in the data store.
I have defined a selectors object whose property values are functions that select data from the store. The selectData method uses the getState method to get the data from the data store and invokes each selector function to generate the data that is rendered by the component. (The use of the entries, map, and reduce methods produces an object with the same property names as the selectors prop with values that are produced by invoking each selector function.)

Selecting a subset of the store data
The object returned by the getState method is a snapshot of the data in the store, which isn’t automatically updated when the store changes. The usual React change detection features don’t work on the store because it is not part of a component’s state data. As a consequence, changes made to the data in the store do not trigger a React update.
I subscribe to updates in the componentDidMount method. The result from the subscribe method is a function that can be used to unsubscribe from updates, which I invoke in the componentWillUnmount method.
The argument to the subscribe method is a function that will be invoked when there have been changes to the data store. No argument is provided to the function, which is just a signal that there has been a change and that the getState method can be used to get the new contents of the data store.
Redux doesn’t provide any information about what data has been changed and so I defined the handleStoreChange method to inspect the data obtained by each of the selector functions to see whether the data that the component renders has changed. I use the component state data feature to keep track of the displayed data and use the setState method to trigger updates. It is important to perform a state change only when the data displayed by the component has changed; otherwise, an update would be performed for every change made to the data store.

Receiving change notifications from the data store
Actions can be dispatched using the dispatch method, which is the same dispatch to which the React-Redux package provided access in Chapter 19 when I needed to dispatch multiple actions.

Dispatching an action
The ability to get the current data from the store, receive change notifications, and dispatch actions provides all the features to create a basic connector component that provides a rudimentary equivalent to the React-Redux package I used in the example application. To create the facility to connect components to the data store through the Redux API, I added a file called CustomConnector.js to the store folder and added the code shown in Listing 20-7.
I don’t recommend using a custom connector in real projects. The React-Redux package has additional features and has been thoroughly tested, but combining core React features with the Redux data store API provides a useful example of how advanced features can be created.

Using a custom data store connector
As I explained in Chapter 19, a reducer is a function that processes an action and updates the data store. A reducer enhancer is a function that accepts one or more normal reducers and uses them to add additional features to the data store.
The combineReducers function is a reducer enhancer that comes built-in to Redux and that I used in Chapter 19 to keep the reducer logic for the model and state data separate.
Reducer enhancers are useful because they receive the actions before they are processed, which means they can alter actions, reject them, or handle them in special ways, such as processing them using multiple reducers, which is what the combineReducers function does.

Resetting the data in the store
Redux provides support for data store middleware, which are functions that receive actions after they have been passed to the dispatch method and before they reach the reducer, allowing them to be intercepted, transformed, or processed in some other way. The most common uses for middleware are to add support for actions that perform asynchronous tasks and to wrap actions in functions so they can be dispatched conditionally or in the future.
There are middleware packages available that address common project needs and that you should consider instead of writing custom code. The redux-promise package supports asynchronous actions (see https://github.com/redux-utilities/redux-promise ), and the redux-thunk package supports action creators that return functions (see https://github.com/reduxjs/redux-thunk ). I find, however, that neither of these packages works in just the way I require, so I prefer to create my own middleware.
A middleware component will usually process an action and then pass it on to the next component in the chain by invoking the next function.
This function is able to change or replace the action object before it is passed on to the next middleware component. It is also possible to short-circuit the chain by invoking the dispatch method received by the outer function or do nothing at all (in which case the action won’t be processed by the data store). The middleware component that I defined in Listing 20-12 checks to see whether the action is an array, in which case it passes on each object contained in the array to the next middleware component for processing.
The middleware function is passed as an argument to the Redux applyMiddleware function, whose result is then passed as an argument to the createStore function.
Multiple middleware functions can be passed as separate arguments to the applyMiddleware function, which will chain them together in the order they have been specified.
There is no change in the behavior of the application, but the code is more concise and easier to understand.
Most projects will not need to modify the behavior of the data store, and if they do, the middleware features described in the previous chapter will be sufficient. But if middleware doesn’t provide sufficient flexibility, a more advanced option is to use an enhancer function, which is a function that takes responsibility for creating the data store object and that can provide wrappers around the standard methods or define new ones.
The applyMiddleware function I used earlier is an enhancer function. This function replaces the data store’s dispatch method so that it can channel actions through its chain of middleware components before they are passed to the reducer.
The enhancer dispatches actions asynchronously, returning a Promise that is resolved once the action has been dispatched. There are currently no tasks in the example application that need asynchronous work, and so I have introduced a delay before dispatching actions to similar a background activity.
Now it gets more complex: the result of the outer function is a function that receives the createStore function. The word function appears too many times for the previous sentence to make immediate sense, and it is worth unpacking what happens.

Using an enhanced data store
The previous sections demonstrated that you can work directly with the Redux API to connect components to the data store. For most projects, however, it is simpler and easier to use the React-Redux package as demonstrated in Chapter 19. In the sections that follow, I describe the advanced options that the React-Redux package provides for configuring how components are connected to the data store.
The connect function can accept some additional arguments for advanced features and can receive arguments expressed in different ways. In this section, I explain the options for using the arguments you are already familiar with and introduce the new arguments and demonstrate their use.
The first argument to the connect function selects the data from the store for the component’s data props. Usually, the selectors are defined as a function that receives the value from the store’s getState method and returns an object whose properties correspond to the prop names. The selector function is invoked when there is a change to the data store, and the higher-order component created by the connect function uses the shouldComponentUpdate lifecycle method (described in Chapter 13) to see whether any the changed values require the connector component to update.
One problem with creating connectors that are applied to multiple components is that too much data is selected, which can lead to unnecessary updates when a change in the data store affects a prop that is used by one component but not another. The TableConnector component is a connector for both tables of product and supplier data, but only the supplier data requires the suppliers prop to be mapped from the data store. For the product table, not only does this mean that the computation of the suppliers property is wasted, but it causes updates when data that it does not display is changed.
The additional argument—which is conventionally named ownProps—allows each instance of a connector component to be customized through the standard React prop features. In Listing 20-21, I used the ownProps argument to decide which props are mapped to the data store based on the value of a prop named needSuppliers applied to the connector component. If the value is true, then a suppliers prop is mapped to the data store and the products prop is mapped otherwise.
There is no difference in the behavior of the application, but behind the scenes, each presentation component that is connected to the data store by the ConnectedTable components uses different props.
Don’t worry too much about optimizing updates until you find you have a performance problem. Almost all optimization adds complexity to a project, and you may find that the performance penalty incurred by your unoptimized code is not discernable or not enough of a problem to worry about. It is easy to get bogged down in trying to optimize away problems that may not exist, and a better approach is to write the clearest, simplest code you can and then optimize the parts that don’t behave the way you require.
As I explained in Chapter 19, the second connect argument, which maps between function props, can be specified as an object or a function. When an object is provided, the value of each of the object’s properties is assumed to be an action creator function and is automatically wrapped in the dispatch method and mapped to a function prop. When a function is provided, the function is given the dispatch method and is responsible for using it to create function prop mappings.
You can omit the second argument to the connect function, in which the dispatch method is mapped to a prop, also named dispatch, which allows the component to create actions and dispatch them directly.
The connect function accepts a third argument that is used to compose the props before they are passed to the presentation component. This argument, known as mergeProps, is a function that receives the mapped data props, the function props, and the connected components props and returns an object that merges them into the object used as the props for the presentation component.
The mergeProps function in Listing 20-24 combines the properties from each prop’s object. The properties are copied from the objects in the order specified, which means the function copies from ownProps last and also means props received from the parent will be used when there are props with the same name.
Name | Description |
|---|---|
pure | By default, a connector component will be updated only when its own props change or when one of the selected values from the data store changes, which allows the higher-order component (HOC) created by connect to prevent updates when no prop or data change has been made. Setting this property to false indicates that the connector component may rely on other data, and the HOC will not try to prevent updates. The default values for this property is true. |
areStatePropsEqual | This function is used to override the default equality comparison for the mapStateToProps values to minimize updates when the pure property is true. |
areOwnPropsEqual | This function is used to override the default equality comparison for the mapDispatchToProps values to minimize updates when the pure property is true. |
areMergedPropsEqual | This function is used to override the default equality comparison for the mergeProps values to minimize updates when the pure property is true. |
areStatesEqual | This function is used to override the default equality comparison for the entire component state to minimize updates when the pure property is true. |
In this chapter, I described the APIs provided by Redux and the React-Redux package and demonstrated how they can be used. I showed you how to connect a component directly to the data store using the Redux API, how to enhance the data store and its reducers, and how to define middleware components. I also demonstrated the advanced options available when using the React-Redux package, which can be used to manage a component’s connection to the data store. In the next chapter, I introduce URL routing to the example application.
At the moment, the selection of content displayed to the user is controlled by the application’s state data. Some of that state data is specific to a single component, such as the Selector component, which manages the choice between products and supplier data. The rest of the data is in the Redux data store and is used by the connected components to decide whether the data table or editor components are required and to obtain the data to populate those components’ content.
Question | Answer |
|---|---|
What is it? | URL routing uses the browser’s current URL to select the content presented to the user. |
Why is it useful? | URL routing allows applications to be structured without the need for shared state data, which becomes encoded in the URL, which also makes it easier to change the structure of an application. |
How is it used? | Navigation elements are rendered that change the browser’s URL without triggering a new HTTP request. The new URL is used to select the content presented to the user. |
Are there any pitfalls or limitations? | Thorough testing is required to ensure that all of the URLs to which the user can navigate are handled correctly and display the appropriate content. |
Are there any alternatives? | URL routing is entirely optional, and there are other ways to compose an application and its data, as demonstrated in earlier chapters. |
Problem | Solution | Listing |
|---|---|---|
Create a navigation element | Use the Link component | 4, 13 |
Respond to navigation | Use the Route component | 5–6 |
Match a specific URL | Use the Route component’s exact prop | 7 |
Match several URLs | Specify the URLs as an array in the Route component’s path prop or use a regular expression | 8–9 |
Select a single route | Use the Switch component | 10 |
Define a fallback route | Use the Redirect component | 11, 12 |
Indicate the active route | Use the NavLink component | 14, 15 |
Choose the mechanism used to represent the route in the URL | Select the router component | 16 |
In this chapter, I continue using the productapp project created in Chapter 18 and used most recently in Chapter 20. To prepare for this chapter, open a new command prompt, navigate to the productapp folder, and run the command shown in Listing 21-1 to add a package to the project. The React Router package is available for a range of application types. The package installed in Listing 21-1 is for web applications.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application
To get started, I am going to use URL routing in the Selector component so that it doesn’t need its own state data to keep track of whether the user wants to work with products or suppliers.
Three components are required to set up a basic routing configuration. The Router component is used to provide access to the URL routing features. There are different ways of using the URL for navigation, each of which has its own React-Router component that I describe in the “Selecting and Configuring the Router” section. The convention is to import the component you require, which is BrowserRouter in this case, and assign it the name Router, which is then used as a container for the content that requires access to the routing features.
React-Router is by far the most widely used routing package for React projects and is a good place to start for most applications. There are other routing packages available, but not all of them are specific to React and can require awkward adaptations.
If you can’t get along with React-Router, then the best alternative is Backbone ( https://backbonejs.org ). This well-regarded package provides routing for any JavaScript application and works well with React.
The navigation URL is specified using the to prop, and this Link will navigate to the /products URL. Navigation URLs are specified relative to the application’s starting URL, which is http://localhost:3000 during development. That means that specifying /products for the to prop of a Link component tells it to render an element that will navigate to http://localhost:3000/products. These relative URLs will continue to work when the application is deployed and has a public URL.
This Route component has been configured to wait until the browser navigates to the /products URL, at which point it will show the ProductDisplay component. For all other URLs, this Route component will not render any content.

Adding navigation elements
The Link components have been rendered to produce anchor (elements whose tag is a) elements, and the value of the to prop has translated into URLs for the anchor element’s href attributes. When you click one of the anchor elements, the browser navigates to a new URL, and the corresponding Route component displays its content. If the browser navigates to a URL for which no Route component has been configured, then no content is displayed, which is why a component was not shown until one of the links had been clicked.
Do not try to create your own anchor elements for navigation because they will cause the browser to send an HTTP request to the server for the URL you specify with the effect that the application will be reloaded. The anchor elements rendered by the Link component have event handlers that change the URL using the HTML5 History API without triggering a new HTTP request.
Name | Description |
|---|---|
path | The prop is used to specify the URL or URLs that the component should wait for. |
exact | When this prop is true, only URLs that precisely equal the path prop are matched, as demonstrated in the “Restricting Matches with Props” section. |
sensitive | When this prop is true, matching URLs is case-sensitive. |
strict | When this prop is true, path values that end in a / will only match URLs whose corresponding segment also ends with a /. |
component | This prop is used to specify a single component that will be displayed when the path prop matches the browser’s current URL. |
render | This prop is used to specify a function that returns the content that will be displayed when the path prop matches the browser’s current URL. |
children | This prop is used to specify a function that will always render content, even when the URL specified by the path prop doesn’t match. This is useful for displaying content in descendent components or components that are not rendered in response to URL changes, as described in Chapter 22. |
The value of the component prop should not be a function because it can lead to a new instance of the specified component being created each time that the application updates.

Using the Route component’s render prop
The function passed to the render prop receives an object that provides information about the state of the routing system, which I describe in Chapter 22.
One of the most difficult aspects of using URL routing is making sure that the URLs you want to support are correctly matched by Route components. The Route component provides a range of features that allow you to expand or narrow the range of URLs that will be matched, which I describe in the sections that follow.
I replaced the ProductDisplay and SupplierDisplay components with content generated by a method called renderMessage. There are three Link components, which target the URLs /data/one, data/two, and /people/bob.

Matching URLs with the Route component
One Route component matches the /data/one URL, both match the /data/two URL, and neither matches /people/bob, and so no content is displayed.
The default behavior of the Route component can lead to over-matching, where a component matches a URL when you don’t want it to. I might want to distinguish between the /data and /data/one URLs, for example, so that the first URL displays a list of data items and the second displays the details of a specific object. The default matching makes this difficult because a path prop of /data matches any URL whose first segment is /data, regardless of how many segments the URL contains in total.

Making exact matches
When set to true, the strict prop is used to restrict matches for a path that has a trailing slash to URLs that have one too, so a path of /data/ will only match the /data/ URL and not /data. The strict prop does match URLs with additional segments, however, so that a path of /data/ will match /data/one.
The sensitive prop is used to control case sensitivity. When true, it will allow matches only when the case of the path prop matches the case of the URL, so a path of /data will not match a /Data URL.
The value of the Route component’s path prop can be an array of URLs, which causes content to be displayed if any of them are matched. This can be useful when the same content is required in response to URLs that don’t have a common structure (such as displaying the same component in response to /data/list and /people/list) or when a specific number of exact matches are required, such as matching /data/one and /data/two but not any other URL that starts with /data, as demonstrated in Listing 21-8.
At the time of writing, there is a mismatch with the prop types that are expected by the Route component that results in a JavaScript console warning when an array is used. This warning can be ignored and may be fixed by the time you read this chapter. See Chapters 10 and 11 for details of how the data types that a component expects for its props can be specified.

Using an array to specify paths
Not all combinations of URLs can be expressed using individual segments, and the Route component supports regular expressions in its path prop for more complex matches, as shown in Listing 21-9.
Most programmers have a tendency to express routes with the fewest regular expressions possible, but the result can be a routing configuration that is hard to read and breaks easily when changes are required. When deciding how to match URLs, keep expressions simple and use a path array to expand the range of URLs that a Route can match without using regular expressions that are difficult to understand.
The first item in the path array matches URLs whose first segment is data and second segment is one or three. The second item matches URLs whose first segment is people and whose second segment starts with b. The result is that the Route component will match the /data/one, /data/two, and /people/bob URLs but not the /data/two and /people/alice URLs.
See https://github.com/pillarjs/path-to-regexp for the full range of regular expression features that can be used to match URLs.
The Switch component checks its children in the order they are defined, which means that the Route components must be arranged so that the most specific URLs appear first. A Route component with no path prop will always match the current URL and can be used as the default by the Switch component, similar to the default clause in a regular JavaScript switch statement.

Using a Switch component
The use of the Switch component allows me to render content when the application first starts before the user has clicked one of the navigation links. However, this is only one way to select content for the default URL, and a more elegant approach is to use the Redirect component, as described in the next section.
The to prop specifies the URL that the Redirect component will navigate to. The Redirect component won’t be used if the Route components are able to match the current URL. But if the Switch component reaches the Redirect component without having found a matching Route, then redirection to /products will be performed.
Name | Description |
|---|---|
to | This prop specifies the location to which the browser should be redirected. |
from | This prop restricts the redirection so that it is performed only when the current URL matches the specified path. |
exact | When true, this prop restricts redirection so that it is performed only when the current URL exactly matches the from prop, performing the same role as the Route component’s exact prop. |
strict | When true, this prop restricts redirection so that it is performed only when the current URL ends with a / if the path also ends with a /, performing the same role as the Route component’s strict prop. |
push | When true, the redirection will add a new item to the browser’s history. When false, the redirection will replace the current location. |
The new Redirect will perform a redirection from the /old/data URL to /suppliers. The order of selective Redirect components is important, and they must be placed before the nonselective redirections are performed; otherwise, the Switch will not reach them as it works its way through the list of routing components.
Name | Description |
|---|---|
to | This prop is used to specify the location that clicking the link will navigate to. |
replace | This prop is used to specify whether clicking the navigation link will add an entry to the browser’s history or replace the current entry, which determines whether the user will be able to use the back button to return to the previous location. The default value is false. |
innerRef | This prop is used to access a ref for the underlying HTML element. See Chapter 16 for details of refs. |

Passing on classes to the navigation element
Name | Description |
|---|---|
activeClassName | This prop specifies the classes that will be added to the anchor element when the link is active. |
activeStyle | This prop specifies the styles that will be added to the anchor element when the link is active. Styles are specified as a JavaScript object whose properties are the style names. |
exact | When true, this prop enforces exact matching, as described in the “Matching URLs” section. |
strict | When true, this prop enforces strict matching, as described in the “Matching URLs” section. |
isActive | This prop can be used to specify a custom function that determines whether the link is active. The function receives match and location arguments, as described in Chapter 22. The default behavior compares the current URL with the to prop. |

Responding to route activation

Restricting URL matching for highlighting
The NavLink component doesn’t allow classes to be removed when the activeClassName value is applied, which means that I can’t accurately re-create the original effect from the example project. I demonstrate how to create this functionality with a custom navigation component in Chapter 22.
Name | Description |
|---|---|
basename | This prop is used when the application isn’t at the root of its URL, such as http://localhost:3000/myapp. |
getUserConfirmation | This prop is used to specify the function used to obtain user confirmation for navigation with the Prompt component, described in Chapter 22. |
forceRefresh | When true, this prop forces a complete refresh during navigation with an HTTP request sent to the server. This undermines the point of a rich client-side application and should be used only for testing and when browsers are unable to use the History API. |
keyLength | Each change in navigation is given a unique key. This prop is used to specify the length of the key and defaults to six characters. The key is incorporated into the location objects that identify each navigation location, described in Chapter 22. |
history | This prop allows a custom history object to be used. The history object is described in Chapter 22. |

Using hash routing
You may see a URL like http://localhost:3000/suppliers/#/suppliers when the browser first reloads. This happens because the browser reloads from its current URL, which is then assumed to be the base URL for the application. Manually navigate to http://localhost:3000 and you should see the URL shown in the figure.
Name | Description |
|---|---|
basename | This prop is used when the application isn’t at the root of its URL, such as http://localhost:3000/myapp. |
getUserConfirmation | This prop is used to specify the function used to obtain user confirmation for navigation with the Prompt component, described in Chapter 22. |
hashType | This prop sets the style used to encode the routing in the URL. The options are slash, which creates the URL style shown in Figure 21-11; noslash, which omits the leading / after the # character; and hashbang, which creates URLs such as #!/products by inserting an exclamation mark after the # character. |
In this chapter, I showed you how to use the React-Router package to add URL routing to a React application. I explained how routing can simplify applications by moving state data into the URL and how Link and Route components are used to create navigation elements and respond to URL changes. In the next chapter, I describe the advanced URL routing features.
Question | Answer |
|---|---|
What is it? | The advanced routing features provide programmatic access to the URL routing system. |
Why is it useful? | These features allow components to be aware of the routing system and the currently active route. |
How is it used? | Access to the advanced routing features is provided by props. |
Are there any pitfalls or limitations? | These are advanced features, and care is required to ensure that they are properly integrated into components. |
Are there any alternatives? | These are optional features. Applications can use the standard features described in Chapter 21 or avoid URL routing entirely. |
Problem | Solution | Listing |
|---|---|---|
Receive details of the routing system in a component | Use the props provided by the Route component or use the withRouter higher-order component | 3, 4, 10–12, 19–23 |
Get details of the current navigation location | Use the location prop | 5 |
Get URL segments from the current route | Add parameters to the URL | 6–9 |
Navigate programmatically | Use the methods defined by the history prop | 13, 14 |
Prompt the user before navigation | Use the Prompt component | 15–17 |
In this chapter, I continue using the productapp project from Chapter 21. To prepare for this chapter, change the router that is used by the application from HashRouter to BrowserRouter, so that the HTML5 History API is used for navigation, and simplified the Link and Router components, as shown in Listing 22-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .

Running the example application
Name | Description |
|---|---|
match | This prop provides information about how the Route component matched the current browser URL. |
location | This prop provides a representation of the current location and can be used for navigation instead of URLs expressed as strings. |
history | This prop provides an API that can be used for navigation, as demonstrated in the “Navigating Programmatically” section. |
Name | Description |
|---|---|
url | This property returns the URL that the Route has matched. |
path | This property returns the path value used to match the URL. |
params | This property returns the route params, which allow segments of a URL to be mapped to variables, as described in the “Using URL Parameters” section. |
isExact | This property returns true if the route path exactly matches the URL. |

Details provided by the match routing prop
Name | Description |
|---|---|
key | This property returns a key that identifies the location. |
pathname | This property returns the path of the location. |
search | This property returns the search term of the location URL (the part of the URL that follows the ? character). |
hash | This property returns the URL fragment of the location URL (the part that follows the # character). |
state | This property is used to associated arbitrary data with a location. |

Displaying details of the location routing prop
Using the location prop as the value for a Link component’s to prop isn’t especially useful at the moment because it is only able to navigate to the current location. As you will see, components can be used to respond to multiple routes and may receive a series of locations over time, which makes using a location object both useful and more convenient than working with URLs expressed as strings.

Receiving URL parameters through the match prop

Responding to a URL parameter by selecting content
URL parameters are not just a convenient way for a component to receive the contents of a URL segment. They also decouple the structure of the URL from the components that are targeted by it, allowing the structure of the URL to be altered or multiple URLs to target the same content without modifying the component. The component in Listing 22-7, for example, depends on the datatype URL parameter but doesn’t have any dependency on the part of the URL from which it is obtained. This means that the component will work with a path such as /info/:datatype but will can also be matched by a path such as /diagnostics/routing/:datatype without requiring changes to the component’s code.
The advantage of URL parameters is that the component just needs to know the names of the URL parameters it requires and not the details of where they appear in the URL.
Optional URL parameters are denoted with a question mark (the ? character) after the parameter name, so datatype? indicates an optional parameter that will be given the name datatype if there is a corresponding segment in the URL. If there is no segment, the path will still match, but there will be no datatype value. In Listing 22-9, I have updated the RouteInfo component so that it displays details of both the match and location objects if there is no datatype value.
For a complete list of the different ways that URL parameters can be specified, see https://github.com/pillarjs/path-to-regexp , which is the GitHub repository for the package that processes URLs.
The value of the datatype parameter will be undefined if no segment in the URL has been matched. The changes in the listing and the addition of the optional URL parameter allow the component to respond to a wider range of URLs without requiring additional Route components to be used.
A Route will add props to the components it displays but can’t provide them directly to other components, including the descendants of the components it displays. To avoid prop threading, the React-Router package provides two different approaches for providing access to routing data in descendant components, as described in the following sections.
The most direct way to get access to routing data is to use a Route in the render method. To demonstrate, I added a file called ToggleLink.js to the src/routing folder and used it to define the component shown in Listing 22-10.
This is the same component I used to highlight the active route in the SportsStore application in Part 1.
The Route component’s children prop is used to render content regardless of the current URL and is assigned a function that receives the routing context data. The path prop is used to indicate interest in a URL, and when the current URL matches the path, the routeProps object passed to the children function includes a match object that defines the properties described in Table 22-4.
The ToggleLink component allows me to solve a minor niggle that arises between the NavLink component and the Bootstrap CSS framework. The NavLink works by adding a class to the anchor element it renders when a path is matched and removing it the rest of the time. This causes a problem for some combinations of Bootstrap classes because the order in which they are defined in the CSS stylesheet means that some classes, such as btn-primary, won’t take effect until a related class, such as btn-secondary, are removed.

Accessing routing data directly in a component

Using the withrouter HOC
The withRouter function doesn’t provide support for matching paths, which means that the match object is of little use. The location object, however, provide details of the application’s current location, and the history object can be used for programmatic navigation, as described in the next section.
Name | Description |
|---|---|
push(path) | This method navigates to the specified path and adds a new entry in the browser’s history. An optional state property can be provided that is available through the location.state property. |
replace(path) | This method navigates to the specified path and replaces the current location in the browser’s history. An optional state property can be provided that is available through the location.state property. |
goBack() | This method navigates to the previous location in the browser’s history. |
goForward() | This method navigates to the next location in the browser’s history. |
go(n) | This method navigates to the history location n places from the current location. Use positive values to move forward and negative values to move backward. |
block(prompt) | This method blocks navigation until the user responds to a prompt, as described in the “Prompting the User Before Navigation” section. |
The onClick handler passes the history object received from the Route component to the handleClick method, which uses the push method to navigate to the location specified by the to prop. There is no visible difference because the anchor elements rendered by the Link components were already styled to appear as buttons, but the ToggleLink component now handles its navigation directly.
Clicking the button sets the doRedirect property to true, which triggers an update that renders the Redirect component. The doRedirect property is set back to false automatically so that the component’s normal content is rendered again. The result is the same as Listing 22-13, and choosing an approach is a matter of preference and personal style.
Name | Description |
|---|---|
message | This prop defines the message displayed to the user. It can be expressed as a string or as a function that accepts a location object and returns a string. |
when | This prop will prompt the user only when its value evaluates to true and can be used to conditionally block navigation. |
Only a single Prompt is used, but it doesn’t matter where it is rendered because it doesn’t perform any action until the application changes to a new location, at which point the user will be asked to confirm navigation. In Listing 22-15, I added a Prompt to the Selector component.
Only one Prompt is needed, and you should not render additional Prompt instances in the components that perform navigation, such as the ToggleLink component in the example application. You will receive a warning in the JavaScript console if you render multiple Prompt components.

Prompting the user before navigating
If you prefer using the history object for navigation, the block method can be used to set up a prompt that will be presented to the user, as demonstrated in the next section.

Using a custom prompt
Notice that I still need to use a Prompt, which is responsible for triggering the process that displays the CustomPrompt.

Generating routes programmatically
Name | Description |
|---|---|
/products/table | This URL will display the table of products. |
/products/create | This URL will display the editor to allow a new product to be created. |
/products/edit/4 | This URL will display the editor to allow an existing product to be edited, where the last URL segment identifies the product to change. |
/suppliers/table | This URL will display the table of suppliers. |
/suppliers/create | This URL will display the editor to allow a new supplier to be created. |
/suppliers/edit/4 | This URL will display the editor to allow an existing supplier to be edited, where the last URL segment identifies the supplier to change. |
In the sections that follow, I will update the components in the application so that the data store is used only for the model data, while the details of which content should be displayed to the user is represented in the URL. (This kind of hard separation is only one approach, and you can take a softer line if it suits your project so that some state data is handled in the data store and some through URLs. As with so much in React development, there is no absolute correct approach.)
This component performs the same task as the ProductDisplay and SupplierDisplay components but receives the data type it is responsible for as an argument, which allows the EditorConnector and TableConnector components to be created.
The component no longer uses the data store to work out whether the user is editing or creating an object and gets this information from the URL, along with the id value when an object is being edited.
Notice that I use Number to parse the id URL parameter, which is presented as a string. I need the id value to be a number in order to locate objects.
I have used the ability to merge props, described in Chapter 20, to create wrappers around the data store action creator so that data is saved to the store and then the history object is used for navigation. The cancel action is no longer required and can be handled directly by navigating away from the current location.
The withRouter and connect functions both produce components that try to minimize updates using the shouldComponentUpdate method, which is described in Chapter 13. When the withRouter and connect functions are used together, the result can be a component that doesn’t always update because the React-Router and React-Redux packages perform simple comparisons on props and don’t realize that a change has occurred. To avoid this problem, simplify the props structure to allow changes to be more easily detected.
Once again, I have used the withRouter and connect functions to produce a component that has access to the routing data and the data store. The editing function is handled by navigating to a URL that indicates the data type and id value. Deleting data is a task handled entirely by the data store and requires no navigation.

Using URL routing to coordinate components
In this chapter, I showed you how to use the advanced features provided by the React-Router package. I demonstrated how to create components that are aware of the routing system, how to use URL parameters to provide components with easy access to data from the current route, and how to use the routing features programmatically. I also demonstrated how components can participate in the routing system while also being connected to Redux, allowing state data to be handled via URLs while the application’s model data is managed by a data store. In the next chapter, I show you how to consume a RESTful web service.
Question | Answer |
|---|---|
What is it? | Web services act as the data repository for an application, allowing data to be read, stored, modified, and deleted using HTTP requests. |
Why is it useful? | Web services fit neatly into the features available in browsers and avoid having to deal with local storage issues. |
How is it used? | Web services are not all implemented the same way, but the general approach is to send HTTP requests where the request method identifies the operation to be performed and the request URL identifies the data to be operated on. |
Are there any pitfalls or limitations? | The inconsistent nature of web service implementations means that each web service can require a slightly different set of requests. Care must be taken when consuming the web service in a component to ensure that requests are not sent each time there is an update. |
Are there any alternatives? | Modern web browsers support local storage options, which can be a good alternative for some projects. The main drawback, however, is that each client has its own data, which misses out on some of the advantages of a single central repository. |
Problem | Solution | Listing |
|---|---|---|
Get data from a web service | Create a data source that makes HTTP requests and feed the data back into the application using a callback that invokes the setState method. | 1–11 |
Perform additional data operations | Extend the data source to send different combinations of HTTP methods and URLs to indicate the required operation. Trigger the requests by responding to component events | 12–15 |
Handle request errors | Use a try/catch block to catch the error and pass it to a component so that a warning can be displayed to the user. | 16–19 |
Consume a web service with a data store | Use middleware to intercept the data store actions and send the required requests to the web service. Once a request has completed, forward the action to the data store so that it can be updated. | 20–24 |
In this chapter, I continue using the productapp project from Chapter 22 that was modified in the chapters since. Some preparation is required to install additional packages to the project and create the web service that the application will rely on.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Name | Description |
|---|---|
json-server | This package provides a web service that the application will query for data. This command is installed with the save-dev command because it is required for development and is not part of the application. |
npm-run-all | This package allows multiple commands to be run in parallel so that the web service and the development server can be started at the same time. This command is installed with the save-dev command because it is required for development and is not part of the application. |
axios | This package will be used by the application to make HTTP requests to the web service. |
The json-server package can work with JSON or JavaScript files. If a JSON file is used, its contents will be modified to reflect changes requests made by clients. Instead, I have chosen the JavaScript option, which allows data to be generated programmatically and means that restarting the process will return to the original data. This isn’t something that you would do in a real project, but it is useful for the example because it makes it easy to return to a known state, while still allowing the application access to persistent data.
The changes to the scripts section of the package.json file use the npm-run-all package so that the HTTP development server and json-server are started by npm start.

Running the example application

Testing the web service
The configuration I have chosen for this chapter means that there are two HTTP servers running. The React development server is listening for requests on port 3000 and provides the HTML document that bootstraps the application, along with the JavaScript and CSS files required to present the application to the user. The RESTful web service is listening for requests on port 3500 and responds with data. This data is expressed in the JSON format, which means it is easily processed by a JavaScript application but should not be presented directly to most users.
The most common approach for delivering and storing application data is applying the Representational State Transfer pattern, known as REST, to create a data web service. There is no detailed specification for REST, which leads to a lot of different approaches that fall under the RESTful banner. There are, however, some unifying ideas that are useful in web application development.
The core premise of a RESTful web service is to embrace the characteristics of HTTP so that request methods—also known as verbs—specify an operation for the server to perform, and the request URL specifies one or more data objects to which the operation will be applied.
The first segment of the URL—api—conventionally indicates that the request is for data. The next segment—products—is used to indicate the collection of objects that will be operated on and allows a single server to provide multiple services, each of which with its own data. The final segment—2—selects an individual object within the products collection. In the example, it is the value of the id property that uniquely identifies an object and that would be used in the URL, in this case, specifying the Lifejacket object.
The HTTP verb or method used to make the request tells the RESTful server what operation should be performed on the specified object. When you tested the RESTful server in the previous section, the browser sent an HTTP GET request, which the server interprets as an instruction to retrieve the specified object and send it to the client.
Verb | URL | Description |
|---|---|---|
GET | /api/products | This combination retrieves all the objects in the products collection. |
GET | /api/products/2 | This combination retrieves the object whose id is 2 from the products collection. |
POST | /api/products | This combination is used to add a new object to the products collection. The request body contains a JSON representation of the new object. |
PUT | /api/products/2 | This combination is used to replace the object in the products collection whose id is 2. The request body contains a JSON representation of the replacement object. |
PATCH | /api/products/2 | This combination is used to update a subset of the properties of the object in the products collection whose id is 2. The request body contains a JSON representation of the properties to update and the new values. |
DELETE | /api/products/2 | This combination is used to delete the product whose id is 2 from the products collection. |
There are considerable differences in the way that web services are implemented, caused by differences in the frameworks used to create them and the preferences of the development team. It is important to confirm how a web service uses verbs and what is required in the URL and request body to perform operations.
Common variations include web services that won’t accept any request bodies that contain id values (to ensure they are generated uniquely by the server’s data store) and web services that don’t support all of the verbs (it is common to ignore PATCH requests and only accept updates using the PUT verb).
You may have noticed that the editor components don’t allow the user to provide a value for the id property. This is because the web service that I create in this chapter generates id values automatically to ensure uniqueness.
Throughout this chapter, I use the Axios library to send HTTP requests to the web service because it is easy to use, deals with common data types automatically, and doesn’t require convoluted code to deal with features like CORS (see the “Making Cross-Origin Requests” sidebar). Axios is widely used in web application development, although it is not specific to React.
Axios isn’t the only way to send HTTP requests to web services. The most basic option to use the XMLlHttpRequest object that provided the original API for making requests using JavaScript (and which is capable of handling a range of data types, despite the XML in the name). The XMLHttpRequest object is awkward to use but has wide browser support, and you can get further details at https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest . (Axios uses XMLHttpRequest to make HTTP requests but simplifies how they are created and processed.)
The Fetch API is a recent API provided by modern browsers that is intended to replace XMLHttpRequest and is described at https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API . The Fetch API is supported by recent releases of the mainstream browsers but not by older browsers, which can be a problem for some applications.
If you are using GraphQL, then you should consider using the Apollo client, as described in Chapter 25.
I go through the steps required to consume a web service in the sections that follow, beginning with requesting the initial data that the application will display to the user and then adding support for storing and updating objects.
The RestDataSource class defines a constructor that receives the base URL for the web service and defines a GetData method that calls the SendRequest.
I imported the HTTP functionality from the axios package and assigned it the name Axios. The SendRequest method uses Axios to send an HTTP request through the request method, where the details of the request are specified using a configuration object that has method and url properties.
Axios provides methods for sending different types of HTTP request—the get, post, and put methods, for example, but using the approach in the listing makes it easier to apply features that affect all request types, as you will see when I add error handling later in the chapter.
Name | Description |
|---|---|
status | This property returns the status code for the response, such as 200 or 404. |
statusText | This property returns the explanatory text that accompanies the status code, such as OK or Not Found. |
headers | This property returns an object whose properties represent the response headers. |
data | This property returns the payload from the response. |
config | This property returns an object that contains the configuration options used to make the request. |
request | This property returns the underlying XMLHttpRequest object that was used to make the request, which can be useful if you require direct access to the API provided by the browser. |
This approach is more concise, but it is important to make sure you put the parentheses in the right places, such that the await keyword is applied to the object returned by the SendRequest method and the data property is read from the object that it produces. Without care, you can easily create a situation where the HTTP request is sent but the response is ignored if you don’t follow this pattern.
The next step is to get the data into the component so that it can be displayed to the user. In Listing 23-11, I have updated the IsolatedTable component so that it creates a data source and uses it to request data from the web service.
The term isolated in the name of the component indicates that the component doesn’t share data with any other components and deals directly with the web service. In the “Consuming a Web Service with a Data Store” section, I show you an alternative approach where components share data via the data store.
The data is requested in the componentDidMount method, which ensures that the HTTP request won’t be sent until after the component has rendered its content. The callback functions provided to the GetData method update the component’s state data, which will trigger an update and ensure that the data is presented to the user.
Do not request data in the render method. As I explained in Chapter 13, a component’s render method can be called often, and starting tasks in the render method can generate large numbers of unnecessary HTTP requests and increase the number of updates that React has to perform as it processes the response data.
Even when using the componentDidMount method, care should be taken when making requests from components that may be unmounted and remounted, which is the case for the IsolatedTable component in the example, which will be mounted by the routing system for the /isolated URL and unmounted when the user navigates to another location. Each time the component is mounted, it will request fresh data from the web service, which may not be what the application requires. To avoid unnecessary data requests, the data can be lifted up to a component that won’t be unmounted, stored in a context (as described in Chapter 14), or incorporated into a data store, as described in the “Consuming a Web Service with a Data Store” section.

Getting data from the web service
The request configuration object passed to the Axios.request method uses a data property to specify the payload for the request, which allows the application to provide JavaScript objects and leave Axios to serialize them automatically.
When you implement data source methods, you will find that some adjustment is required to accommodate the range of ways that web services can be implemented. For example, the example web service will automatically assign a unique id property value to objects that are received in POST requests and include the complete object in the response. The Store method in Listing 23-12 uses the data property to get the complete object from the HTTP response and uses it to invoke the callback, which ensures that the application receives the object as it has been stored by the web service. Not all web services operate this way—some may require the application to include a unique identifier or will return only the identifier in the response instead of sending the complete object.
The web service returns the complete updated object, which is used to invoke the callback function. Once again, not all web services will return the complete object, but it is a common approach because it ensures that any additional transformations that are applied by the web service are reflected in the client.

Consuming a web service
The changes made by the application are stored in the web service, which means you can reload the browser and the changes will still be visible. The configuration of the json-server package at the start of the chapter means that restarting the development tools will reset the data presented to by the web service. See the SportsStore application in Chapter 8 for an example of using json-server for truly persistent data that does not reset when the tools are restarted.
The advantage of consolidating all the requests through the SendRequest method is that I can use a single try/catch block to handle errors for all request types. The catch block handles errors that arise from requests and invokes the callback function that is received as a constructor argument.
The Axios package presents detailed errors when something goes wrong and includes the status code from the response and any descriptive text the web service supplies. For most applications, however, it doesn’t make sense to present this information to the user, who won’t understand what has happened or know how to fix it. Instead, I recommend presenting a general error message to the user and logging details of the problem at the server so that common issues can be identified.

Displaying an error message
By default, browsers enforce a security policy that only allows JavaScript code to make asynchronous HTTP requests within the same origin as the document that contains them. This policy is intended to reduce the risk of cross-site scripting (CSS) attacks, where the browser is tricked into executing malicious code, which is described at http://en.wikipedia.org/wiki/Cross-site_scripting . For web application developers, the same-origin policy can be a problem when using web services because they are often outside of the origin that contains the application’s JavaScript code. Two URLs are considered to be in the same origin if they have the same protocol, host, and port, and they have different origins if this is not the case. The URL that I use for the RESTful web service in this chapter has a different origin to the URL used by the main application because they use different TCP ports.
The Cross-Origin Resource Sharing (CORS) protocol is used to send requests to different origins. With CORS, the browser includes headers in the asynchronous HTTP request that provide the server with the origin of the JavaScript code. The response from the server includes headers that tell the browser whether it is willing to accept the request. The details of CORS are outside the scope of this book, but there is an introduction to the topic at https://en.wikipedia.org/wiki/Cross-origin_resource_sharing , and the CORS specification is available at www.w3.org/TR/cors .
CORS is something that happens automatically in this chapter. The json-server package that provides the RESTful web service supports CORS and will accept requests from any origin, while the Axios package that I use to make HTTP requests automatically applies CORS. When you select software for your own projects, you must either select a platform that will allow all requests to be handled through a single origin or configure CORS so that the server will accept the application’s requests for data.
The components I defined in the previous section are isolated from one another and are coordinated only through the URL routing system. The advantage of this approach is simplicity, but it can lead to repeatedly requesting the same data from the web service as the user navigates around the application and each component sends its HTTP requests when it is mounted. If the application uses a data store, then the data can be shared between components.
One new action is required, which is to request the data from the web service. This hasn’t been required previously because the data store has been automatically initialized with data. The action type is GET_DATA, and Listing 23-20 defines a getData action creator.
The createRestMiddleware function accepts data sources for the product and supplier data and returns middleware that deals with the new GET_DATA action and the existing STORE, UPDATE, and DELETE actions by sending a request to the web service and then dispatching additional actions when the result is received, using the existing features of the data store.
The order is important when considering how the data store is used by the existing components in the application. The multiActions middleware created in Chapter 20 allows arrays of actions to be dispatched, and this must come first; otherwise, the new middleware won’t properly process actions.

Using the web service with the data store
In this chapter, I introduced a web service and used it to obtain the data displayed by the user, store new data, make changes, and delete data. I used the Axios library in this chapter, but there are many other options available, and consuming a web service in a React application is a relatively simple process. In the next chapter, I introduce GraphQL, which is a more flexible alternative to REST for web services.
Question | Answer |
|---|---|
What is it? | GraphQL is a query language that produces APIs. |
Why is it useful? | GraphQL provides the client with flexible access to data, ensuring that the client receives only the data it requires and allowing new queries to be formulated without requiring server-side changes. |
How is it used? | At the server, a schema is defined and implemented using resolver functions. The client uses the GraphQL language to send queries and request changes. |
Are there any pitfalls or limitations? | GraphQL is complex and writing a useful schema can require skill. |
Are there any alternatives? | Clients can use RESTful web services, as described in Chapter 23. |
I describe the features of GraphQL that are most useful for React development. For a complete description of GraphQL, see the GraphQL specification at https://facebook.github.io/graphql/June2018 .
Problem | Solution | Listing |
|---|---|---|
Define a GraphQL service | Describe the queries and mutations that will be supported and implement the resolvers that provide them | 3, 4, 8–10, 20–21 |
Query a GraphQL service | Specify the query name and the fields that are required in the result | 7, 11, 27, 28 |
Filter results | Specify query arguments | 12–19 |
Make changes using a GraphQL service | Specify the mutation and the fields for the update | 22–24 |
Parameterize queries | Use query variables | 25, 26 |
Request the same set of fields from multiple queries | use a query fragment | 29 |
In this chapter, I continue to use the example application from Chapter 23. To prepare for this chapter, open a command prompt, navigate to the productapp folder, and run the commands shown in Listing 24-1 to add packages to the project.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Name | Description |
|---|---|
graphql | This package contains the reference implementation of GraphQL. |
express | This package provides an extensible HTTP server and will be the foundation of the GraphQL server used in this chapter. |
express-graphql | This package provides GraphQL services over HTTP through the express package. |
graphql-import | This package allows GraphQL schemas to be defined in multiple files and imports schemas more easily than reading a file directly. |
cors | This package enables Cross-Origin Resource Sharing (CORS) for the Express HTTP server. |

Running the example application
RESTful web services are easy to get started with, but they can become inflexible as the needs of the client evolve and the number of client applications using the service increases.
Changes that suit one application can’t be made because they cause problems in another application, work backs up so that changes are not made in time for client-application release dates, and infrastructure development teams struggle to balance competing demands for features. You may not have any avenue for requesting changes when you rely on a third-party web service because you are one of dozens or hundreds of development teams all asking for new features.
The result is a poor fit between the application and the web service it relies on. Clients often have to make multiple requests to the web service to get the data they require; this is then merged into a useful format. The client has to understand how the objects returned from different REST requests relate to one another and often has to request data that is then discarded because only a subset of the data fields is required.
The underlying problem with REST web services is that the data they provide and the way they provide it are fixed, and that becomes an issue as the needs of the client application change. GraphQL addresses this problem by allowing the client more control over what data is requested and how it is expressed, with the result that client-side applications can add features that use data in new ways with fewer server-side changes required.
GraphQL isn’t suitable for every situation. GraphQL is complex and not as widely understood as REST, which can make it difficult to find experienced developers and robust and well-tested tools and libraries. And GraphQL can shift work that would have been performed by the client application into the server, which can increase costs in the data center and require licenses for back-end servers that support GraphQL.
It is important to consider GraphQL as an option, especially if your application is likely to require ongoing development after deployment or you intend to develop or support multiple client applications. But my advice is not to rush into using GraphQL until you are sure that a REST web service won’t give you the flexibility you need.
I am going to create a custom GraphQL server that presents the same data as the web service from Chapter 23 The process of creating the GraphQL service isn’t required by all projects, especially when consuming a third-party API, but understanding what is happening at the server provides useful insights into how GraphQL works. In the sections that follow, I’ll go through the process of describing the types of requests that the client will be able to make and write the code required to deal with those requests.
I use the GraphQL reference implementations to create a simple GraphQL server for this chapter. It makes it easy to demonstrate how GraphQL works but doesn’t make any provision for working with real data.
For small and simple projects, adding persistent data support with a package such as Lowdb ( https://github.com/typicode/lowdb ) or MongoDB ( https://www.mongodb.com ) may be suitable.
For more complex projects, the Apollo server ( https://github.com/apollographql/apollo-server ) is the most common choice. There are open-source and paid-for plans available, and there is a wide range of data integration options available, such as using GraphQL as a front end to existing REST web services.
Name | Description |
|---|---|
ID | This type represents a unique identifier. |
String | This type represents a string. |
Int | This type represents a signed integer |
Float | This type represents a floating-point value |
Boolean | This type represents a true or false value. |
The square brackets indicate that the products field of the supplier type will be an array of ID values.
Don’t worry about the GraphQL type system too much at the moment. It will start to make more sense as you see how the different parts of the server fit together and are used by the client.
The first statement defines a query called products that will return an array of product objects. The second statement defines a query called suppliers that will return an array of supplier objects.
Each resolver is a function whose name corresponds to one of the queries and that returns data in the format declared by the schema. The data used by the products and suppliers resolvers uses data loaded from the restData.js file.
The GraphQL server will be run by Node.js, which does not support JavaScript modules at the time of writing, which means that the import and export keywords cannot be used. Instead, the require function is used to declare a dependency on a file, and module.exports is used to make code or data available outside of a JavaScript file.
The graphql package provides the buildSchema function, which takes a schema string and prepares it for use. The contents of the schema file are imported using the graphql-import package and passed to the buildSchema function. The express-graphql package integrates GraphQL support into the popular express server, which I have configured to listen on port 3600.

The GraphiQL browser
The query is basic, but it reveals a lot about how GraphQL queries work. The query keyword is used to differentiate between requests to retrieve data and mutations, which are used to make changes (and which are described in the “Making GraphQL Mutations” section). The query itself is enclosed in curly brackets, also known as braces. Inside the braces, the query name is specified, which is suppliers in this case.
When you query a GraphQL service, you must specify the data fields that you want to receive. Unlike a REST web service, which always presents the same data structures, GraphQL allows the client to specify the results it wants to receive, enclosed in another set of braces. The query in Listing 24-7 selects the id, name, city, and products fields.
There is no wildcard that allows all fields to be selected. If you want to receive all the fields for a data type, then you must include all of them in the query.
This may not seem like a huge departure from a REST web service, but even with this basic query, the client is able to select the fields it requires and the order in which they will be expressed.
The GraphQL service is working, and it can be used to get product and supplier data, which meets the basic needs of the data tables in the example application. However, one of the most powerful features of GraphQL is the ease with which it supports related data in queries, allowing a single query to return results that contain multiple types. In Listing 24-8, I have changed the products field to the schema for the supplier data type.
Writing the schema gives the best insight into the queries that a GraphQL service supports, but that isn’t always possible. If you are not writing your own schema, the first thing to do is look for developer documentation; many public GraphQL services publish comprehensive schema documentation, such as the GitHub API, described at https://developer.github.com/v4 .
Many services also support GraphiQL or similar tools, most of which support schema navigation. GraphiQL, for example, makes it easy to explore the schema through its Docs link, which lets you navigate through the queries and mutations that a service supports.
The special __schema query data type is used to request information about the schema. You can find more details of the GraphQL introspection features at https://graphql.org/learn/introspection .
The data is processed so that each supplier object has a products property. The products property is a function that will resolve the related data and that will be invoked only if the client has requested this data field, which ensures that the server doesn’t do work to get data that has not been asked for.
Notice that the client specifies the fields required for both the supplier objects and the related product data, which ensures that only the data required by the application is retrieved.
In addition to regular queries, the GraphQL specification includes support for subscriptions, which provide ongoing updates for data that is changing on the server. Subscriptions are not widely or consistently supported, and I don’t describe them in this book.
The resolver function receives an object whose properties correspond to the query arguments. To get the id value specified in the query, the resolver functions read the args.id property. I can simplify this code by destructing the argument object, as shown in Listing 24-14.
Notice I used the parseInt function to convert the id argument for comparison. A direct comparison using === between an ID value and a JavaScript Number value will return false.
The methods used to receive field arguments are invoked for every request, which can create a substantial amount of work for the server. Consider using a memoization package for complex results, such as fast-memoize ( https://github.com/caiogondim/fast-memoize.js ).
The first mutation, called storeProduct, uses a dedicated input type, which allows the client to provide values to describe the changes that are required. Input types are defined using the input keyword and support the same features as regular types. In the listing, I have defined an input type called productInput that has an optional id field and mandatory name, category, and price fields. This is broadly duplicative of the product type already defined in the schema, which is a common approach because you can’t use regular types as the arguments to mutations.
Mutations are performed using the mutation keyword, which is the counterpart to the query keyword used in the previous example. The name of the mutation is specified, along with a product argument that provides id, name, category, and price. The fields required from the result are then specified, and, in this case, all of the fields defined by a product are selected.
Notice that the mutation uses id values in the product field to express the relationship between supplier and product objects, but the result includes the product names. The mutation gets its result from the updated presentation data, showing that the result of a mutation need not be directly related to the data it receives.
To complete this chapter, I am going to describe some useful features that build on those described earlier. These are all optional, but they can be used to make the GraphQL service easier to work with.
Variables are applied to the query or mutation and are defined using a name that starts with a dollar sign (the $ character) and assigned a type. In this case, the query defines a variable called id whose type is a mandatory ID. Inside the query, the variable is used as $id and is passed to the product query argument.

Using a query variable
Variables may not appear useful when using GraphiQL, but they can simplify client development, as demonstrated in Chapter 24.
In this chapter, I introduced GraphQL. I explained the role of the schema and its resolvers, and I demonstrated the process for creating a simple GraphQL service for static data. I showed you how to define queries to get data from a GraphQL service and how to use mutations to make changes. All of the example in this chapter were performed using the GraphiQL tool, and in the next chapter, I show you how to consume GraphQL in a React application.
In this chapter—the last in this book—I show you the different ways that a GraphQL service can be consumed by a React application. I show you how to work directly with HTTP requests, how to integrate GraphQL with a data store, and how to use a dedicated GraphQL client.
In this chapter, I continue using the productapp project from Chapter 24 and the GraphQL service it contains. To prepare for this chapter, the changes described in the following sections are required.
Later in the chapter, I create components that receive GraphQL data directly, which requires additional packages. Open a new command prompt, navigate to the productapp folder, and run the commands shown in Listing 25-1.
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-react-16 .
Name | Description |
|---|---|
apollo-boost | This package contains the Apollo GraphQL client with a configuration that is suitable for most projects. |
react-apollo | This package contains the React integration for the Apollo client. |
The new resolvers remove an item from the data arrays and return the value of their id parameters, corresponding to the ID type used in the schema. When a product is removed, any reference to it from a supplier is also removed to avoid errors when subsequently querying for supplier data.
I have also changed the storeProduct and storeSupplier functions so they will treat a request whose object has an id value of zero the same as if it contained no id value at all. This is a useful technique when dealing with form data because it means that all the form values can be sent to the server without needing to remove the id property to differentiate between new and modified objects.

Running the example application
The use of HTTP and the structure of the request and response make it easy to integrate GraphQL into a React application, following the same pattern I used in Chapter 23 for working with a RESTful web service.
Each query is defined with a GraphQL expression and a name, which the application will use to retrieve the data from the response. The queries rely on the variable feature described in Chapter 24. Next, I added a file called mutations.js in the src/graphql folder and defined the mutations that the application will need, as shown in Listing 25-9.
Separating the queries from the mutations isn’t required since they are all just strings, but I find it helpful, especially for applications that make heavy use of GraphQL.
There are mutations for storing and deleting product and supplier objects, and the name of each mutation is used in the name property, following the same pattern established for the queries.
Notice that I parse the value of the price property into a Number before the data is sent to the server. The GraphQL server checks the data it receives against the types defined in the schema and will reject string values, which are what form elements typically produce, if another type, such as Float, is required.

Using GraphQL data

Using GraphQL data in the data store
If you encounter errors, stop the development tools and start them again using npm start. This will reset the data used by the GraphQL server and undo the effects of changes made in previous sections.
I demonstrated how GraphQL can be used with a Redux data store in the previous section because it shows how easily the data can be used and provides a comparison against working with a RESTful web service.
There is a different approach, which is to use a package that replaces the data store and provides GraphQL data directly to the components that need it while caching data to avoid the kind of repeated HTTP requests that navigation between isolated components can lead to.
The package that I use in this section is called Apollo Client, which is the client-side package from the same developers as the Apollo GraphQL server that I mentioned in Chapter 24 (but that works with any GraphQL server). Full documentation for the Apollo Client is available at https://www.apollographql.com/docs/react ).
The examples in this chapter rely on the packages installed at the start of the chapter.
A new ApolloClient object is created to manage the relationship to the GraphQL server, and its constructor accepts a configuration object. The uri property of the configuration object specifies the URL for GraphQL requests. There are other configuration options, but the defaults are suitable for most projects (see www.apollographql.com for details).
The ApolloProvider component is used to integrate GraphQL features with React, and the client prop is assigned the ApolloClient object.
To simplify the example, I have removed the content contained within the Selector component and the data store. I will define the components displayed by the selector directly shortly.
I have removed the Redux data store from the application only to simplify the example application. Apollo Client and Redux can be used in the same application, although you should be careful not to store data in Redux that is being managed by Apollo Client because the two will easily get out of sync.
The next step is to create components that will act as a bridge between GraphQL and the content displayed to the user. This is the same basic approach that I have been using throughout this part of the book, and it means that the content rendered to the user is produced by components that do not depend directly on a specific mechanism for data, whether it be the Redux data store, a RESTful web service, or a GraphQL client. I added a file called GraphQLTable.js to the src/graphql folder and added the code shown in Listing 25-22.
I picked Apollo Client because it is flexible and easy to get on with. The main alternative is Relay ( https://facebook.github.io/relay ), which is developed by Facebook. Relay is more difficult to get started with and only works with GraphQL schemas that follow a particular structure.
There are also packages that offer a subset of the features provided by Apollo Client or Relay, such as Adrenaline ( https://github.com/gyzerok/adrenaline ).
Name | Description |
|---|---|
data | This property returns the data produced by the query. |
loading | This property returns true when the query is being processed. |
error | This property returns details of any query errors. |
variables | This property returns the variables used for the query. |
refetch | This property returns a function that can be used to resend the query, optionally with new variables. |
When the component is first rendered and the request is sent to the GraphQL server, the loading value is true. When the request has completed, the component updates, with the loading value as false, and provides the result through the data property.
If you don’t specify an inline function, as shown, then the event object will be passed to the refetch function, which will attempt to use it as the source of variables for the query and encounter an error.

Using a GraphQL client package
If you encounter errors, stop the development tools and start them again using npm start. This will reset the data used by the GraphQL server and undo the effects of changes made in previous sections.
If you use the F12 Developer Tools to see the network requests that the browser makes, you will see that queries for data are sent the first time that the routing buttons are clicked but not when the same table is selected again. Click the Reload Data button to invoke the query’s refresh function and trigger a new query.
Name | Description |
|---|---|
mutation | This prop specifies the mutation that will be sent to the server. |
variables | This prop specifies the variables for the mutation. Variables can also be provided when the mutation is performed. |
refetchQueries | This prop specifies one or more queries to be performed when the mutation has been completed. |
update | This prop specifies a function that is used to update the cache when the mutation has been completed. |
onCompleted | This prop specifies a callback function that is invoked when the mutation has completed. |

Using a mutation
Name | Description |
|---|---|
readQuery | This method is used to read data from the cache associated with a specific query. An error will be thrown if you try to read data that is not in the cache, which typically occurs if a query has not yet been executed. |
writeQuery | This method is used to update the data in the cache associated with a specific query. |
The removeItemFromCache method in Listing 25-25 uses the readQuery method to retrieve the cached data associated with the products query, filters out the deleted item, and writes the remaining items back to the cache using the writeQuery method. The readQuery method accepts an object with query and an optional variables property, and the write query method accepts an object with query, data, and an optional variables property. The result is that when you click the Delete button for a product, the object is deleted from the local cache after the mutation has been completed without the need for an additional query.
Notice that this example combines the update and refetchQueries props on the Mutation. I need to keep the supplier data consistent when a product is deleted, but using the readQuery method for data not in the cache produces an error. To keep the example simple—and not to duplicate too much logic from the GraphQL server’s resolvers—I use the update prop to perform a simple excision from the cache and the refetchQueries prop to get fresh suppliers data.
This component builds on the same features used for the table. A Query is used to request the data from the GraphQL server, with the variables prop being used to provide the variables required by the query. A Mutation is used to store the data, with the onCompleted prop used to navigate away from the editor once the mutation has completed.
Notice that I have not updated the cached data. Apollo Client has a clever feature where mutations that alter a single object and have responses with an id property and properties that have been changed are automatically pushed into the cache and used by other Query objects. In the case of the editor component, this means that changes to a product or supplier are automatically shown in the data table, without the need to update the cache or re-query for the data.

Supporting supplier data and editing
If you encounter errors, stop the development tools and start them again using npm start. This will reset the data used by the GraphQL server and undo the effects of changes made in previous sections.
In this chapter, I showed you the different ways that a React application can consume a GraphQL service. I showed you how to use GraphQL in isolated components, how to intercept data store actions and service them using GraphQL, and how to adopt a GraphQL client that manages the data on behalf of the application.
And that is all I have to teach you about React. I started by creating a simple application and then took you on a comprehensive tour of the different building blocks in the framework, showing you how they can be created, configured, and applied to create web applications.
I wish you every success in your React projects, and I can only hope that you have enjoyed reading this book as much as I enjoyed writing it.