Building a React App With Server-Side Swift

In this tutorial, you’ll learn to create a dynamic web application with React.js and integrate it with a Vapor server-side application. By Mattia Fochesato.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Routing With React Router

If you want your app to have many pages, you must implement a Router component, and then you’ll be able to specify a path for each component.

There are many types of router:

  • HashRouter allows you to create a single-page app. The page change is instantaneous since the browser isn’t changing the page. It’s all handled by the router on the client side.
  • BrowserRouter is the standard routing method. Each page has its path. Changing a page is slower than the HashRouter, and the state management can be a little trickier.
  • React Router supports other types of Routers as well. You can find all of them inside their documentation.

In this tutorial you’ll use HashRouter since it’s easier to implement. Open index.js and replace the < App /> tag with this:

{/* 1 */}
<HashRouter>
  {/* 2 */}
  <Routes>
    {/* 3 */}
    <Route exact path="/" element={<BookList />} />
    {/* TODO: Define any additional Route */}
  </Routes>
</HashRouter>

Going through this step by step:

  1. The HashRouter tag allows you to create a single-page web app with client-side routing.
  2. The Routes tag component will contain a list of Routes, which define the paths available in the app.
  3. This defines the root path /, which will soon show the BookList component.

Don’t forget to import the components at the beginning of the index.js file:

// Allows you to use ReactRoute components inside this file
import { HashRouter, Routes, Route } from "react-router-dom";
import BookList from "./BookList";
Note: It’s necessary to import every component that you’ll use in React. However, some editors like VSCode automatically import the required components as you type your code.

Now, save the file, and React will update the preview with the new index. The page at http://localhost:3000 is now empty since you still haven’t put any components inside it. That’s your next step.

Creating a Responsive Page With Bootstrap

Bootstrap uses a grid system to align content on the webpage. Thanks to containers, rows and columns, you can create responsive web apps with a few lines of code without worrying too much about the layout.

To start creating the user interface using Bootstrap, open BookList.js and replace {/* TODO: Replace with React components */} with the following:

{/* 1 */}
<Container>
  {/* 2 */}
  <Row>
    {/* 3 */}
    <Stack direction="horizontal" className="mt-3 mb-3">
      <h2>Book List</h2>
      {/* TODO: Add Button to navigate to the "New Book" page */}
    </Stack>
    {/* TODO: Add the Table component */}
  </Row>
</Container>

Here’s what each step does:

  1. You use the Container tag to center the content of your component horizontally.
  2. Since Bootstrap uses a grid system, you use Row to represent a row, which will be an entry that displays a book.
  3. The Stack tag creates a flexible container, which will have a horizontal direction and additional attributes such as mt-3 for the top margin and mb-3 for the bottom margin.

Now the page at http://localhost:3000 will look like this.

The Book list page with its title

At this point, the only thing missing is the table that displays the list of books in the library.

Creating a Table to Display Books

Before implementing the table, you need to define a variable to hold the data that React will fetch from the Vapor app.

Since the variable you’ll define will be used to draw the interface, React needs to know when the value of the variable changes. So you have to use the useState() hook to define new variables that can change the components’ layout.

In BookList.js, replace // TODO: Define variables and functions needed with:

// Define all the variables needed for the book list
const [booksData, setBooksData] = useState(null);
// TODO: Add function to load books

useState() needs an initial value and it returns the current state and a function.

You’ve created a state variable called booksData with the starting value of null. You can change the value of booksData by calling setBooksData(), passing the new value as a parameter.

Still in BookList.js, replace {/* TODO: Add the Table component */} with the following code:

{/* Bootstrap Table */}
<Table bordered hover>
  {/* Table Header */}
  <thead>
    <tr>
      <th>Book Name</th>
      <th>Author</th>
    </tr>
  </thead>
  {/* Table Body */}
  <tbody>
    {/* 1 */}
    {booksData &&
      booksData.map(({ id, title, author }) => (
        <>
          {/* 2 */}
          <tr key={id}>
            {/* 3 */}
            <td>{title}</td>
            <td>{author}</td>
          </tr>
        </>
      ))}
  </tbody>
</Table>

This will construct the table that shows the list of books. Here’s what’s happening:

  1. Check whether booksData is null. Then, render the data as a table row.
  2. Set the key of the row. React will use it to calculate diffs and optimize the performance of redrawing the UI.
  3. Show the book’s title and author as a table cell.

Now, the web page of the React app looks like this.

Book List page with title

What’s missing? Actual books! :] Your next step is fetching them from the Vapor app.

Fetching Data From the Vapor app

In BookList.js, replace // TODO: Add function to load books with:

// Function that will load the books from the back end
function loadBooks() {
  // 1
  setBooksData(null);
  // 2
  fetch("http://localhost:8080/books/")
    // 3
    .then((response) => response.json())
    // 4
    .then((json) => setBooksData(json));
}

// 5
useEffect(() => {
  loadBooks();
}, []);

This fetches and stores the books in the booksData variable. A lot’s going on here. This code:

  1. Clears the booksData variable to remove previously loaded books.
  2. Fetches the books from the backend using the fetch() function.
  3. Converts the response from a JSON string to a JavaScript object.
  4. Saves the object in the booksData variable using setBookData(json).
  5. Calls loadBooks() via the useEffect() hook.

useEffect() accepts a function and an array of dependencies as an argument. If any dependencies’ values change, the hook triggers the function. React also executes the function one time on the first render of the component.

Here, there are no dependencies to track since you only need to execute the loadBooks() function when the component is loaded.

It’s crucial to call loadBooks() from the useEffect() hook, because loadBooks() fetches data and causes the content on the view to change.

Check the page at http://localhost:3000 again, and you’ll see the list of books displayed.

Book list page with its title and table

Congrats on your first achievement! Now, what about adding new books to the list? For that, you’ll need a new component and a new page.