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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Building a React App With Server-Side Swift
25 mins
- Getting Started
- Installing Node.js and npm
- Creating the React App
- Adding Bootstrap Theme and React Router
- Understanding React App Structure
- Creating the BookList Component
- Routing With React Router
- Creating a Responsive Page With Bootstrap
- Creating a Table to Display Books
- Fetching Data From the Vapor app
- Creating a Page to Add New Books
- Creating a Form
- Handling Form Data
- Building the React App for Production
- Serving the App With Vapor
- Where to Go From Here
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:
- The
HashRouter
tag allows you to create a single-page web app with client-side routing. - The
Routes
tag component will contain a list ofRoute
s, which define the paths available in the app. - This defines the root path
/
, which will soon show theBookList
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";
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:
- You use the
Container
tag to center the content of your component horizontally. - Since Bootstrap uses a grid system, you use
Row
to represent a row, which will be an entry that displays a book. - The
Stack
tag creates a flexible container, which will have ahorizontal
direction and additional attributes such asmt-3
for the top margin andmb-3
for the bottom margin.
Now the page at http://localhost:3000 will look like this.
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:
- Check whether
booksData
isnull
. Then, render the data as a table row. - Set the
key
of the row. React will use it to calculate diffs and optimize the performance of redrawing the UI. - Show the book’s
title
andauthor
as a table cell.
Now, the web page of the React app looks like this.
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:
- Clears the
booksData
variable to remove previously loaded books. - Fetches the books from the backend using the
fetch()
function. - Converts the response from a JSON string to a JavaScript object.
- Saves the object in the
booksData
variable usingsetBookData(json)
. - Calls
loadBooks()
via theuseEffect()
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.
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.