Welcome, new React developers! Today, we're going to learn about handling form input in React. We'll start from the very basics and gradually build up to more complex concepts. Don't worry if you don't understand everything right away – we'll take it step by step.
In web development, forms are a crucial part of user interaction. They allow users to input data that can be sent to a server or processed by your application. Think about when you log into a website, post a comment, or make an online purchase – you're using forms in all these cases!
In React, we handle forms a bit differently than in traditional HTML. React gives us more control over how forms behave and how we process the data. This control allows us to create more interactive and responsive user interfaces.
Let's start with a simple example of a form in HTML:
<form>
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<button type="submit">Submit</button>
</form>
This is a basic form with three main parts:
<label>
that tells the user what information to enter. <input>
where the user can type their username. <button>
to submit the form.In traditional HTML, when you click the submit button, the form data is usually sent to a server, and the page refreshes. But in React, we often want to handle this data ourselves without refreshing the page. This is where React's form handling comes in handy.
Now, let's create our first React component with a form:
import React from 'react';
function SimpleForm() {
return (
<form>
<label htmlFor="username">Username:</label>
<input type="text" id="username" name="username" />
<button type="submit">Submit</button>
</form>
);
}
export default SimpleForm;
This might look very similar to our HTML example, but there are some important differences to understand:
<input>
and <button>
tags are self-closing in this JSX. In HTML, you might see <input>
without a closing tag, but in JSX, we always close our tags, either with a closing tag(</input>)
or a self-closing tag (/>)
This SimpleForm component doesn't do anything yet when you submit it – it's just displaying a form. In the next steps, we'll add functionality to it.
Now that we have our form displaying correctly, let's make it do something when we submit it. We'll modify our component to handle the form submission:
import React from 'react';
function SimpleForm() {
const handleSubmit = (event) => {
event.preventDefault();
console.log('Form submitted!');
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="username">Username:</label>
<input type="text" id="username" name="username" />
<button type="submit">Submit</button>
</form>
);
}
export default SimpleForm;
Let's break down what's new here:
event.preventDefault()
. This is very important! By default, when a form is submitted, the browser tries to send the data to a server and refresh the page. preventDefault()
stops this default behavior, allowing us to handle the submission ourselves without a page refresh. <form>
tag, we've added onSubmit={handleSubmit}.
This is how we tell React to run our handleSubmit function when the form is submitted. The curly braces {} are used in JSX to embed JavaScript expressions.Now, when you click the submit button (or press Enter in the input field), instead of the page refreshing, you'll see 'Form submitted!' in the browser's console (you can open the console in your browser's developer tools to see this).
This is a big step! We've gone from a static form to one that can respond to user actions. Next, we'll look at how to actually get the data the user has entered.
Now that we can handle the form submission, let's get the value from our input when the form is submitted:
import React from 'react';
function SimpleForm() {
const handleSubmit = (event) => {
event.preventDefault();
const username = event.target.elements.username.value;
console.log('Submitted username:', username);
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="username">Username:</label>
<input type="text" id="username" name="username" />
<button type="submit">Submit</button>
</form>
);
}
export default SimpleForm;
Let's examine what's new in our handleSubmit function:
const username = event.target.elements.username.value;
<form>
element.Now, when you submit the form, instead of just seeing 'Form submitted!', you'll see 'Submitted username:' followed by whatever you typed into the input field.
This approach of getting the input value when the form is submitted works, but it has limitations. What if we want to know what the user has typed before they submit the form? Or what if we want to validate the input as the user types? For these more advanced use cases, we need to introduce the concept of state.
So far, we're only getting the input value when the form is submitted. But what if we want to know the value as the user types? This is where React's state comes in.
State is like a component's memory. It's where we store data that can change over time. When you update a component's state, React automatically re-renders the component, reflecting the new state in the UI.
Let's modify our component to use state:
import React, { useState } from 'react';
function SimpleForm() {
const [username, setUsername] = useState('');
const handleChange = (event) => {
setUsername(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
console.log('Submitted username:', username);
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
name="username"
value={username}
onChange={handleChange}
/>
<button type="submit">Submit</button>
</form>
);
}
export default SimpleForm;
This is a big change, so let's break it down step by step:
const [username, setUsername] = useState('');
This creates a state variable called username and a function to update it called setUsername. The empty string ''
is the initial value of username.
const handleChange = (event) => {
setUsername(event.target.value);
};
This function is called every time the input changes (i.e., every time the user types or deletes a character). It updates our username state with the new value of the input.
<input>
, we add two new props:value={username}
onChange={handleChange}
value={username}
sets the value of the input to our username state. This means the input will always show the current value of username.
onChange={handleChange}
tells React to call our handleChange function whenever the input changes.
This setup creates what's called a "controlled component". The React state becomes the "single source of truth" for the input value. The input displays what's in the state, and the state updates when the input changes.
With this approach, username will always contain the current value of the input. This allows you to easily use the input value elsewhere in your component, validate it as the user types, or even disable the submit button unless the username meets certain criteria.
We've covered a lot of ground here! We started with a basic form in React, added form submission handling, learned how to get input values, and finally introduced state to create a controlled input.
Here's a quick recap of what we've learned:
Remember, learning React takes time and practice. Don't worry if you don't understand everything right away. Try playing around with this code, make changes, and see what happens. In our next lesson, we'll dive deeper into controlled components and discuss the difference between controlled and uncontrolled components.