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 3 of 4 of this article. Click here to view the first page.

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:

  1. The title and author variables hold the value of the form input elements.
  2. onSubmit() handles the Form data and sends it to the back end.
  3. A Stack tag defines the name of the page and a Button tag navigates to the Book list page.
  4. The Form component accepts the onSubmit() 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.

New book page with its title

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.

Book list page with its add new book button

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:

  1. A Form.Group is just a container for a single input value. With className="mb-3", you specify that this component has a margin-bottom.
  2. The Form.Label component shows a title on top of the input label.
  3. The Form.Control is the text field used to input the book’s title. When the input’s value changes, the app updates the title variable thanks to onChange() that calls setTitle(), passing the value of the label.
  4. 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 of variant.

Now, visit http://localhost:3000/#/newbook, and you’ll see a form like this.

New Book page with its fields

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:

  1. When the user submits the form, e.preventDefault() prevents the browser from redirecting the user to another page.
  2. Make a POST request to the API with the new book’s data.
  3. Encode the new book’s data as a JSON object and place it in the request’s body.
  4. 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.

Book list page with a new book added

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.