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
Creating a Page to Add New Books
You’ll start with a new component that allows users to input the book’s details and send them to the Vapor backend.
In src, create a new file called NewBook.js, and add the following code:
import { useState } from "react";
import { Button, Container, Form, Row, Stack } from "react-bootstrap";
import { NavLink, useNavigate } from "react-router-dom";
function NewBook() {
// 1
const [title, setTitle] = useState("");
const [author, setAuthor] = useState("");
// TODO: Define variables that are needed
// 2
const onSubmit = (e) => {
// TODO: Implement this function
};
return (
<>
{/* Bootstrap container */}
<Container>
<Row>
{/* 3 */}
<Stack direction="horizontal" className="mt-3 mb-3">
<h2>Add a new book</h2>
<Button className="ms-auto" as={NavLink} to="/">Show all books</Button>
</Stack>
{/* 4 */}
<Form onSubmit={onSubmit}>
{/* TODO: Add components to accept user input */}
</Form>
</Row>
</Container>
</>
);
}
export default NewBook;
In this new component:
- The
title
andauthor
variables hold the value of the form input elements. -
onSubmit()
handles theForm
data and sends it to the back end. - A
Stack
tag defines the name of the page and aButton
tag navigates to the Book list page. - The
Form
component accepts theonSubmit()
function. When the user hits the Submit button, the browser calls this function.
You now have the new component, but you still can’t access it. As you did with the BookList
component, you have to add a new route and specify a path.
Open src/index.js and replace {/* TODO: Define any additional Route */}
with the following:
{/* Define the /newbook path that will show the NewBook component */}
<Route path="/newbook" element={<NewBook />} />
And don’t forget to import NewBook
at the beginning of the index.js file:
import NewBook from "./NewBook";
Now, visit http://localhost:3000/#/newbook in your browser to verify the page exists.
It would be great to have a way to access this new page without knowing the path. You can use a Button to take the user to the new page.
Open BookList.js and replace {/* TODO: Add Button to navigate to the "New Book" page */}
with this snippet:
{/* Button used to navigate to the "/newbook" page */}
<Button className="ms-auto" as={NavLink} to="/newbook">Add new book</Button>
By adding this button at the top of the Book List page, you’ll be able to access the new page easily.
You might also notice that the new page loads instantaneously. This is because HashRouter handles all the routing on the client side.
Creating a Form
You’ll ask the user for the information about the new book using the Form
. Bootstrap has beautiful forms that just need a bit more code.
In NewBook.js, replace {/* TODO: Add components to accept user input */}
with the following:
{/* 1 */}
<Form.Group className="mb-3">
{/* 2 */}
<Form.Label>Book</Form.Label>
{/* 3 */}
<Form.Control
type="text"
required
placeholder="Name of the book"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Author</Form.Label>
<Form.Control
type="text"
required
placeholder="Name of the author"
value={author}
onChange={(e) => setAuthor(e.target.value)}
/>
</Form.Group>
{/* 4 */}
<Button variant="primary" type="submit">
Add
</Button>
Here’s the structure of this Form
:
- A
Form.Group
is just a container for a single input value. WithclassName="mb-3"
, you specify that this component has a margin-bottom. - The
Form.Label
component shows a title on top of the input label. - The
Form.Control
is the text field used to input the book’s title. When the input’s value changes, the app updates thetitle
variable thanks toonChange()
that callssetTitle()
, passing the value of the label. - To submit the form, you’ll use the Bootstrap Button, but you have to specify that it’s a
submit
button. You alter the appearance of the button by changing the value ofvariant
.
Now, visit http://localhost:3000/#/newbook, and you’ll see a form like this.
It’s time to save the data that users will enter in the form.
Handling Form Data
Notice that hitting the Add button doesn’t add the book to the list because you still haven’t told React what to do with the form data.
Before completing the implementation of onSubmit()
, you need to declare a new variable. Still in src/NewBook.js, replace // TODO: Define variables that are needed
with:
const navigate = useNavigate();
By using navigate
, you can redirect the user to another page by calling navigate("path")
. React Router provides this function, and you can use it with every Router you choose.
Now, add this code inside onSubmit()
to handle the form submit:
// 1
e.preventDefault();
// 2
fetch("http://localhost:8080/books/", {
method: "POST",
// 3
body: JSON.stringify({ title, author }),
headers: { "Content-Type": "application/json" },
})
// 4
.then(() => {
// Navigate to the book list (index) using React Router
navigate("/");
});
It should be familiar, but take a look anyway:
- When the user submits the form,
e.preventDefault()
prevents the browser from redirecting the user to another page. - Make a
POST
request to the API with the new book’s data. - Encode the new book’s data as a JSON object and place it in the request’s
body
. - With
then()
, you specify what happens after the request is sent to the server.
Now, visit http://localhost:3000/#/newbook, and add a new book to the list using the form you just created.
After the book is created, you’re redirected to the list page, which includes also the new entry.
Congrats! You’re almost done. It’s time to package your React app and ship it to customers.
Building the React App for Production
Now that your app is complete, you’re ready to deploy the production version.
You shouldn’t deploy your development build since it can be slow. When you build your app for production, React removes all the debugging tools and minimizes the source files. This way, your app loads faster.
Quit the running npm start
command and run this command from the frontend folder:
npm run build
This will run the build
script, which generates a build folder containing all the necessary assets to run your app. Then, you can host it on a web server or with Vapor.