How To Build A React Form With Uncontrolled Components

How To Build A React Form With Uncontrolled Components

Now with sweet built-in exercises!

Jan 6, 2023·

4 min read

If you just want to see the result, you can jump to the solution below.

Forms are a common part of most applications.

React applications are no exception. The challenge is that there's more than one way to build a form. Without understanding the differences, it can be hard to know where to start.

Having different tools for different jobs will make it easier to handle new situations.

In this series, we're going to take a look at building the same form with different approaches and React tools.

How Things Are Setup
  1. Key Information: Explanations and links around key topics that will help you understand how to solve the problem.
  2. Try It Out: A code editor with a shell of the solution. Your job is to try to solve the problem by filling in the blank parts of the code editor.
  3. Solution: A code editor with the finished version of the code.

The form will look something like this:

A drawing of the form that's built as part of this blog series.

Key Information

Form Layout

The good news is that you only need a little React knowledge to build a regular form.

Building a form in React is easy. For the most part, it's the same as building a form with standard HTML. All you need is an HTML form element and some input elements with valid labels.

        Enter your name:
        <input name="name">

Input Types

The behavior of an input element changes with its type attribute. The default value is text which refers to your standard text field. In the example above, the type is omitted, so the name input is a text field.

There are many input types, but for the sake of this demo, we'll pick out a few interesting ones:

  • text: the default text field that most forms use.

  • password: similar to the text type, but hides the user's input.

  • hidden: an input field that's...hidden. This can be useful if you want to keep track of some data that should be sent to the server, but you don't want to show the data to the user.

  • submit: A special input type that displays a button. When clicked, the button will submit the form.

  • reset: A special input type that displays a button. When clicked, the button will reset the form to its initial state (this input type isn't normally recommended because it can cause problems if a user accidentally clicks the button).

Form Submissions

If you're building a form, you probably want to submit the data to a server.

There are a few different ways to do that. The most basic is to use the browser's default behavior. An input element with the type submit will trigger the submission when clicked. If you want to use this method then the following form element attributes are important to know:

  • action: the URL that handles the form submission

  • method: the type of HTTP method used for the form submission. Both types below will make a request to the action URL. The difference is in how the form data is sent to the server.

    • get (default): the form data is appended to the action URL as params

    • post: the form data is sent as part of the body of the request

<form action="/some-place" method="get">
    <!--Form elements-->

Submitting a form this way is still valid and in some cases it's preferable. Some server side rendered (SSR) frameworks like Remix encourage you to write your forms this way. In Remix's case, their form solution is built on top of the browser's standard behavior.

You write a form like the above and Remix progressively enhances it.

All this means is that if a user has JavaScript enabled then their experience is improved. The fetch API is used to make the request instead. If they don't have JavaScript enabled then it falls back to the default form behavior which will still work.

That said, this isn't the only way to submit a form. In fact, this probably isn't the best way to handle form submissions for most single page applications (SPAs). The typical SPA makes API requests to a backend to handle all data fetching and mutation.

If this sounds like your application then you're going to want to do something different.

A more common approach is to attach an event handler to a form element's onSubmit event. First, you stop the default form behavior. Then you get the form data and make your API request.

function MyForm() {
    return (
        <form onSubmit={event => { /* handle form submission */ }}>
            {/* Form elements */}

Try It Out


Now that you know the basics of HTML forms, let's try building one. If you get stuck, you can jump to the solution below.