As an example, we can develop a simple React application consuming the REST API we created in a previous article. The API provides methods to use an online collection management application. Now our task is to develop a web UI to use these methods.
Before starting development, we need to set up a React.js development environment.
1. React.js Development Environment Set Up
There are several ways to use React.js. The simplest way is just to include React libraries in the <script> tags on the page.
Listing 1.1. Including the React.js library in the HTML page:
This way, we can very quickly start developing React applications, but we cannot use certain advanced features, like JSX, for example. So, a more appropriate solution, especially for large and sophisticated applications, would be to use the
create-react-app tool. To install it, you need Node.js and npm to be installed on your computer:
npm install -g create-react-app
Then you can run the following command in the root directory, where you want to create your project:
.../project-root>npx create-react-app consuming-rest
This command creates a new folder (‘consuming-rest’) with a ready-to-run prototype React application.
Now we can enter the directory and run the application, as follows:
This starts the application in a new browser at http://localhost:3000:
It is a trivial but completely functional front-end application, which we can use as a prototype for creating our UI.
Initially, we can implement a data service to communicate with the server.
2. Backend Communication Service Implementation
In general, it is a good idea to put all related functionalities in one place. Putting our functionality behind a service which exposes certain APIs ensures more flexibility and testability for our application. So, we create a communication service class, which implements all basic CRUD operations for data exchange with the server and exposes these operations as methods for all React components. To make our UI more responsive, we implement the methods as asynchronous. Provided the API is unchanged, we can change the implementation freely and none of the consumers will be affected. To put these concepts into practice, let’s create a mock implementation of the service, which provides mock data for building and testing our UI. Our mock service can look like this.
Listing 2.1. src/shared/mock-item-service.js – mock ItemService:
Based on this, we can build the UI.
3. CRUD UI Implementation
React supports component hierarchies, where each component can have a state and the state can be shared between related components. Also, each component’s behavior can be customized by passing properties to it. So, we can develop the main component, which contains the list of collection items and works as the placeholder for displaying forms for corresponding CRUD actions. Using the stuff generated by the create-react-app tool, we change the content of app.js as follows.
Listing 3.1. src/App.js – the main component as the application frame:
Note that, for now, our app component uses the mock service we created in section 2:
. . .
import ItemService from './shared/mock-item-service';
. . .
Then we will create nested components for basic operations with collection items.
Listing 3.2. src/new-item.js – creating new collection items:
In Listing 3.2, we use the
validator class, which provides a simple validation for newly created or edited collection items. This class can be shared between components, i.e. it can be used in
EditItem components in our case.
Listing 3.3. src/shared/validatior.js – a simple validation for the item form:
Listing 3.4. src/item-details.js – viewing item details:
Listing 3.5. src/edit-item.js – editing existing items:
Here we use the lifting-state-up approach. Instead of maintaining state in each child component and synchronizing the states, and hence the appearance of related components, we lift the shared state up to their closest common ancestor. So, we maintain state in the parent
app component with the usage of callback functions which are passed to child components via properties. Then we call the callback functions inside event handlers in the child components. In these functions, we change the parent component state correspondingly to the user actions triggered in the child components. Based on the parent component state change, React rerenders child components, if appropriate. For example, see how the
App.onEditItem() method is called in the
ItemDetails.onEdit() event handler, which is triggered when the user clicks the Edit button.
This way, we have one-point state management that makes our UI model more consistent.
Note: Redux technology provides an even more consistent and effective way of managing component model state, especially in large applications.
Provided we have all the scripts in place, we can see the main application at http://localhost:3000:
By clicking on an item in the list, we can see the item details:
If we need to edit an item, we can make the detail view editable with the Edit button:
Also, we can add new items with the New Item button:
To have our UI really functional, we need to make it exchange data with the backend.
4. Real Communication
While React doesn’t provide any built-in support for sending requests to the server, we are free to use any communication library inside our React applications. Let’s use Fetch API, which is becoming a standard way to send HTTP requests and is supported in most modern browsers. Provided we have our communication interface defined, we can easily substitute our mock service implementation (see section 2) with a fully functional version, like the following.
Listing 4.1. src/shared/item-service.js – real functional version of ItemService:
Here we also follow the single-responsibility principle and put all configuration settings into one object,
Configuration, which can be imported into all relevant components.
Now we have all the basic modules developed and can put all the things together and run our application.
5. Running the Front-End Application
Provided we have our backend running on http://localhost:8080, we can set its URL in the configuration class.
Listing 5.1. Configuration class – one-point application configuration:
And start up our application:
This time, we see the main application screen with real data from the backend:
We can add new items, like the following screenshot illustrates:
New item added:
So, we have developed a fully functional web application, which supports main collection management operations, i.e. the ability to add, view, update, and delete items. The source code for this article is available at https://github.com/spylypets/consuming-rest. Using the React component model, we can create sophisticated UIs with nested, multi-page views, providing a rich user experience. More details can be found at the React.js official site and sites for related technologies, like:
Redux – state management library.
Formik – HTML form support library.
Jest – Testing React applications.
If you enjoyed this article and want to learn more about React, check out this collection of tutorials and articles on all things React.