- React Tutorial
- React Home
- React Setup
- React Introduction
- React ES6
- React Render HTML
- React JSX
- React Components
- React Class
- React Props
- React Events
- React Conditional
- React Lists
- React Forms
- React Router
- React Memo
- React CSS Styling
- React Hooks
- What is a Hook?
- React useState
- React useEffect
- React useContext
- React useRef
- React useReducer
- React useCallback
- React useMemo
- React Custom Hooks
React Forms
- React forms allow users to interact with and submit data to the application, serving as the bridge between your users and your backend.
- Unlike standard HTML forms, React typically uses a controlled component approach. This means React's state becomes the "single source of truth" for the form data, giving you full control over validation and submission.
Creating a Simple Form
In a controlled form, every time a user types a character, an event handler updates the state. The input's value is then set from that state. This circular flow ensures the input always displays exactly what is in your React state.
import React, { useState } from 'react';
const SimpleForm = () => {
// We initialize the state as an empty string
const [inputValue, setInputValue] = useState('');
const handleChange = (e) => {
// We update the state with the current value of the input
setInputValue(e.target.value);
};
return (
<form>
<label>
Enter text:
<input
type="text"
value={inputValue}
onChange={handleChange}
/>
</label>
<p>You entered: {inputValue}</p>
</form>
);
};
onChange handler while providing a value prop. This will result in a read-only input field that the user cannot type into!
Handling Form Submission
When a user submits a form (by clicking a button or pressing Enter), the browser's default behavior is to refresh the page. In a Single Page Application (SPA), we want to prevent this refresh so we can handle the data with JavaScript.
import React, { useState } from 'react';
const SubmissionForm = () => {
const [inputValue, setInputValue] = useState('');
const handleSubmit = (e) => {
// This is crucial: it stops the browser from reloading the page
e.preventDefault();
// Here you would typically send data to an API
console.log("Processing data:", inputValue);
alert(`Form submitted with value: ${inputValue}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Enter text:
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
</label>
<button type="submit">Submit</button>
</form>
);
};
onSubmit event on the <form> element rather than an onClick on the button. This ensures the form submits correctly when a user presses the "Enter" key.
Handling Different Input Types
Not all inputs work the same way. While text inputs use e.target.value, checkboxes use the checked property. React handles these nuances easily by mapping specific state variables to the correct attributes.
import React, { useState } from 'react';
const InputTypesForm = () => {
const [isChecked, setIsChecked] = useState(false);
const [selectedOption, setSelectedOption] = useState('option1');
return (
<form>
<label>
<input
type="checkbox"
// For checkboxes, we use 'checked' instead of 'value'
checked={isChecked}
onChange={() => setIsChecked(!isChecked)}
/>
Accept Terms and Conditions
</label>
<br />
<p>Select your preference:</p>
<label>
<input
type="radio"
value="option1"
checked={selectedOption === 'option1'}
onChange={() => setSelectedOption('option1')}
/>
Option 1
</label>
<label>
<input
type="radio"
value="option2"
checked={selectedOption === 'option2'}
onChange={() => setSelectedOption('option2')}
/>
Option 2
</label>
</form>
);
};
name attribute if you want them to behave like a standard group where only one can be selected, although React state management often makes the name attribute optional for functionality.
Using Controlled Components
In real-world applications, you'll often have many inputs. Instead of creating a dozen different state variables, you can use a single object to manage the entire form state. This makes your code cleaner and easier to scale.
import React, { useState } from 'react';
const ControlledComponentsForm = () => {
// Managing multiple fields in one state object
const [formData, setFormData] = useState({
username: '',
password: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
// Use the name attribute to update the correct piece of state
setFormData({
...formData,
[name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
alert(`Username: ${formData.username}, Password: ${formData.password}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Username:
<input
type="text"
name="username"
value={formData.username}
onChange={handleChange}
/>
</label>
<br />
<label>
Password:
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</label>
<br />
<button type="submit">Login</button>
</form>
);
};
...formData) before updating a specific field, otherwise you will delete the other fields in your object!
Summary
Working with forms in React involves a shift in mindset: the component state drives what the user sees, and user actions drive updates to that state. This "controlled" approach provides a robust framework for implementing features like real-time validation, conditional formatting, and complex multi-step forms. While manual state management works great for small forms, for massive enterprise forms, developers often look into libraries like Formik or React Hook Form to reduce boilerplate code.