Skip to content

GSG-CA/react-forms-using-hooks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 

Repository files navigation

Forms and inputs

Form elements are sort of unique in HTML because they are stateful. A user can check an <input type="checkbox"> and the DOM will keep track of that "checked" state.

Since React has its own way of keeping track of UI state it's often annoying to keep input state in the DOM and the rest of your state in React/JS. It's common to move input state entirely into React; this is called controlling a component.

Controlled Components

A controlled component is one whose internal state is managed in another place (usually a parent component).

value

We can "control" the value of an input by passing it a value prop.

function Form() {
  return <input value="Hello" />;
}

This isn't very useful as the value is now hard-coded. This value needs to be stateful, so we should move it into React state.

function Form() {
  const [message] = React.useState("Hello");
  return <input value={message} />;
}

However we still have no way to update the value—if the user types into the input nothing will happen.

onChange

To control an input you also need an onChange event handler. This will update the state (and therefore the input's value) whenever the user types.

function Form() {
  const [message, setMessage] = React.useState("Hello");
  return (
    <input
      value={message}
      onChange={(event) => setMessage(event.target.value)}
    />
  );
}

How is this useful

This seems like a lot of ceremony just to make an input work the same way it did without React, but there are advantages.

We can now have as many sources of input value as we like—we aren't limited to the user typing. For example we might want to pre-fill the input based on some other data we have:

function Form(props) {
  const [email, setEmail] = React.useState(props.user.email);
  return (
    <input
      type="email"
      value={email}
      onChange={(event) => setEmail(event.target.value)}
    />
  );
}

Other input types

React tries to normalize all the different HTML inputs. In React text inputs, selects and textareas all work the same way: you pass value and onChange props.

function Form() {
  const [fruit, setFruit] = React.useState("apple");
  return (
    <select value={fruit} onChange={(event) => setFruit(event.target.value)}>
      <option value="apple">Apple</option>
      <option value="orange">Orange</option>
      <option value="banana">Banana</option>
    </select>
  );
}

The value of the select controls which option is highlighted.

Checkboxes and radios

Checkboxes are slightly different—they take a checked prop instead of a value.

function Form() {
  const [checked, setChecked] = React.useState(false);
  return (
    <input
      type="checkbox"
      checked={checked}
      onChange={(event) => setChecked(event.target.checked)}
    />
  );
}

Radio buttons are a combination of both: they take a checked and a value prop. If you have a radio group all using the same value you need to set their checked prop conditionally based on their value:

function Form() {
  const [fruit, setFruit] = React.useState("apple");
  const handleChange = (event) => setFruit(event.target.value);
  return (
    <form>
      <input
        type="radio"
        name="fruit" // name groups the inputs
        value="apple"
        checked={fruit === "apple"}
        onChange={handleChange}
      />
      <input
        type="radio"
        name="fruit"
        value="orange"
        checked={fruit === "orange"}
        onChange={handleChange}
      />
      <input
        type="radio"
        name="fruit"
        value="banana"
        checked={fruit === "banana"}
        onChange={handleChange}
      />
    </form>
  );
}

Workshop Part 4

We're going to build a form that converts temperature. Open up ./index.html; you should see a component called TempConverter that renders a form. Edit this component to add the required inputs:

It should have radio buttons to pick either celsius or fahrenheit scale, and a number input to enter the temperature to be converted. Don't forget that inputs need labels! It should also show the converted temperature inside the output tag.

Here are helper functions to do the temperature conversion:

const celsiusToFahrenheit = (c) => Math.round((c * 9) / 5 + 32);
const fahrenheitToCelsius = (f) => Math.round(((f - 32) * 5) / 9);
Hint (you can click me)

You need to keep track of two state values: which scale the user picked and what temperature they typed. You can derive the converted temperature from these two bits of state.

temp-converter

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages