Form states are a separate topic that needs to be discussed. There are two approaches to handling form states. One of them gives control over the state to the form itself, while the other involves storing it in the user's application. Both approaches have their pros and cons, and these need to be taken into account when choosing one solution or another.
React's documentation calls these approaches controlled and uncontrolled forms. These names are quite an accurate description of what's happening, so we'll use the same terminology here.
Uncontrolled forms
This is an approach where the state of a given form is stored within the form itself and is retrieved only when it is submitted. This is the usual way of working with forms outside of frameworks:
form.addEventListener('submit', (e) => {
const formData = new FormData(e.target);
// Data processing, e.g., sending data to the server
});
The advantages of this method include:
- Simplicity. There's not much code and there's no need to store the state.
- Speed. The browser does all the work itself. Minimum intervention required from user code.
Although it's easy and obvious, this approach has one drawback. This approach makes it impossible to respond to changes in the form as it's being filled out. Where might it be needed? Here are a few examples:
- Autoduplication. Drop-down lists depend on what was typed.
- Input validation while text is being typed. Often implemented as a red frame around the input box.
- Instant filtering. This is often used on reservation or product search services. All you need to do is select a menu item, and the available selection will change.
In this situation, we need controlled forms.
Controlled forms
With this approach, the state of all form elements is tracked by the application code. Any change is analyzed and saved. Depending on the current state of the data, the code decides what to show and what not to show. These forms often don't even have a submit button. Especially when forms carry out data filtering.
const state = {
registrationForm: {
state: 'valid',
data: {
name: '',
email: '',
},
errors: [],
},
};
// https://github.com/sindresorhus/on-change
const watchedState = onChange(state, (path, value) => {
if (path === 'registrationForm.state') {
if (value === 'invalid') {
// Rendering errors stored somewhere in the state
// watchedState.registrationForm.errors
}
}
});
form.elements.name.addEventListener('change', (e) => {
watchedState.registrationForm.data.name = e.target.value;
// Actions: validation, queries, ...
});
form.elements.email.addEventListener('change', (e) => {
watchedState.registrationForm.data.email = e.target.value;
// Actions: validation, queries, ...
});
If you need to submit this form, it'll be much easier to do so than with uncontrolled forms. The data has already been extracted from the form and is ready to be sent.
form.addEventListener('submit', (e) => {
// Data processing, e.g., sending data to the server
// watchedState.registrationForm.data
});
The advantages of this approach:
- It allows you to implement any reaction during a form change before submitting or instead of submitting it.
And its flaws:
- There's significantly more code if you implement it manually.
- They're slower because of the greater number of actions (and possibly intensive reactions). But whether it's a problem or not depends on the specific situation.
Controlled forms require so much more code that people try to automate them in every way possible. Libraries have been created, such as garlic.js, that automatically track form changes and provide callbacks to react to those changes.
There are very many of these libraries available for different frameworks. React, for example, has dozens of them.
What should you use?
In pure JS, unsupervised forms are preferred. It's so much easier and faster. And you can still introduce controls for form data if you need an instant reaction. It's not really a binary choice between one or the other, either. You can use a hybrid approach, introducing controls for data only when you can't do without it.
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.