惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
O
OpenAI News
W
WeLiveSecurity
S
Secure Thoughts
www.infosecurity-magazine.com
www.infosecurity-magazine.com
H
Heimdal Security Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Schneier on Security
Schneier on Security
Cloudbric
Cloudbric
T
Threatpost
T
Troy Hunt's Blog
T
Tenable Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Vulnerabilities – Threatpost
Google Online Security Blog
Google Online Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
The Hacker News
The Hacker News
Know Your Adversary
Know Your Adversary
Forbes - Security
Forbes - Security
Cyberwarzone
Cyberwarzone
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
腾讯CDC
博客园 - 三生石上(FineUI控件)
爱范儿
爱范儿
J
Java Code Geeks
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
T
The Blog of Author Tim Ferriss
MongoDB | Blog
MongoDB | Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
GbyAI
GbyAI
D
Docker
V
Visual Studio Blog
云风的 BLOG
云风的 BLOG
I
InfoQ
WordPress大学
WordPress大学
人人都是产品经理
人人都是产品经理
A
Arctic Wolf
L
LINUX DO - 热门话题
The Cloudflare Blog
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件

Dmitri Pavlutin Blog

Pure Functions in JavaScript: A Beginner's Guide Record Type in TypeScript: A Quick Intro How to Write Comments in React: The Good, the Bad and the Ugly 4 Ways to Create an Enum in JavaScript React forwardRef(): How to Pass Refs to Child Components TypeScript Function Types: A Beginner's Guide How to Use v-model to Access Input Values in Vue Mastering Vue refs: From Zero to Hero Environment Variables in JavaScript: process.env 5 Must-Know Differences Between ref() and reactive() in Vue How to Destructure Props in Vue (Composition API) Triangulation in Test-Driven Development How to Use nextTick() in Vue Programming to Interface Vs to Implementation A Smarter JavaScript Mapper: array.flatMap() Array Grouping in JavaScript: Object.groupBy() How to Access ES Module Metadata using import.meta JSON Modules in JavaScript How to Trim Strings in JavaScript TypeScript Function Overloading How to Debounce and Throttle Callbacks in Vue How to Show/Hide Elements in Vue Sparse vs Dense Arrays in JavaScript How to Fill an Array with Initial Values in JavaScript Covariance and Contravariance in TypeScript What are Higher-Order Functions in JavaScript? How to Use TypeScript with React Components Index Signatures in TypeScript How to Use React useReducer() Hook unknown vs any in TypeScript A Guide to React Context and useContext() Hook How to Use Promise.any() 2 Ways to Remove a Property from an Object in JavaScript 'return await promise' vs 'return promise' in JavaScript How to Use Promise.allSettled() How to Use fetch() with JSON JavaScript Promises: then(f,f) vs then(f).catch(f) What is a Promise in JavaScript? How to Use Promise.all() A Simple Guide to Component Props in React Don't Stop Me Now: How to Use React useTransition() hook A Simple Explanation of JavaScript Variables: const, let, var ES Modules Dynamic Import How to Memoize with React.useMemo() How to Cleanup Async Effects in React Why Math.max() Without Arguments Returns -Infinity How to Debounce and Throttle Callbacks in React Don't Confuse Function Expressions and Function Declarations in JavaScript How to Use ES Modules in Node.js Solving a Mystery Behavior of parseInt() in JavaScript How to Use Array Reduce Method in JavaScript 3 Ways to Merge Arrays in JavaScript A Guide to Jotai: the Minimalist React State Management Library The Difference Between Values and References in JavaScript How to Implement a Queue in JavaScript A Helpful Algorithm to Determine "this" value in JavaScript React useRef() Hook Explained in 3 Steps 7 Interview Questions on "this" keyword in JavaScript. Can You Answer Them? How to Greatly Enhance fetch() with the Decorator Pattern 7 Interview Questions on JavaScript Closures. Can You Answer Them? What's a Method in JavaScript? array.sort() Does Not Simply Sort Numbers in JavaScript How to Solve the Infinite Loop of React.useEffect() The New Array Method You'll Enjoy: array.at(index) What's the Difference between DOM Node and Element? Why Promises Are Faster Than setTimeout()? Everything About Callback Functions in JavaScript How React Updates State 5 Mistakes to Avoid When Using React Hooks 5 Best Practices to Write Quality JavaScript Variables Type checking in JavaScript: typeof and instanceof operators 3 Ways to Check if a Variable is Defined in JavaScript Prototypal Inheritance in JavaScript How to Timeout a fetch() Request How to Learn JavaScript If You're a Beginner A Simple Explanation of React.useEffect() A Simple Explanation of JavaScript Iterators How to Use React Controlled Inputs Everything about null in JavaScript How to Use Fetch with async/await Getting Started with Arrow Functions in JavaScript An Interesting Explanation of async/await in JavaScript Front-end Architecture: Stable and Volatile Dependencies Is it Safe to Compare JavaScript Strings? How to Access Object's Keys, Values, and Entries in JavaScript What Actually is a String in JavaScript? 3 Ways to Shallow Clone Objects in JavaScript (w/ bonuses) Checking if an Array Contains a Value in JavaScript JavaScript Event Delegation: A Beginner's Guide How to Parse URL in JavaScript: hostname, pathname, query, hash 3 Ways to Detect an Array in JavaScript How to Get the Screen, Window, and Web Page Sizes in JavaScript 3 Ways to Check If an Object Has a Property/Key in JavaScript How to Compare Objects in JavaScript Object.is() vs Strict Equality Operator in JavaScript Own and Inherited Properties in JavaScript 5 Differences Between Arrow and Regular Functions How to Use Object Destructuring in JavaScript Your Guide to React.useCallback() 5 JavaScript Scope Gotchas
React Forms Tutorial: Access Input Values, Validate, Submit Forms
Dmitri Pavlutin · 2020-11-10 · via Dmitri Pavlutin Blog

HTML elements like headings <h1>, <h2>, paragraphs <p>, or simple textual output <span> are meant to display information.

On the other side, the forms <form> and input elements like <input>, <select>, <textarea> collect information from the user. Working with forms and input fields requires more effort: you have to access input values, validate the form, submit form data, and handle submission result.

In this tutorial, I'm going to show you how to access the form input values, how to validate and submit forms in React.

Let's get started!

Table of Contents

  • 1. "Register Your Cat" form
  • 2. Form state
  • 3. Form validation
  • 4. Form submission
  • 5. Form's initial data
  • 6. Summary

1. "Register Your Cat" form

A 🐱 cat show event is going to happen in your city. Your task, as a web developer, is to implement a form to register cats for the show.

Let's name the form "Register Your Cat", having the fields:

  • Name: textual input field (required)
  • Color: select field. Available options are white, red, blue, black, cream (required)
  • Age: numeric input field (required)
  • Habits: textual field (optional)

Let's code the first version of "Register Your Cat" form, as a functional React component:


const COLORS = ['white', 'red', 'blue', 'black', 'cream'];

function RegisterYourCatForm() {

return (

<form>

<h2>Register Your Cat</h2>

<label>Name*:</label>

<input />

<label>Color*:</label>

<select>

<option value="">Select color</option>

{COLORS.map(c => <option key={c}>{c}</option>)}

</select>

<label>Age*:</label>

<input />

<label>Habits:</label>

<textarea />

<button type="submit">Submit</button>

</form>

);

}


<RegisterYourCatForm /> component contains a <form> — the HTML element that defines a form.

The form contains input fields: <input /> element is used to introduce Name and Age, <select> element to choose a Color, and <textarea> element to enter longer text of the cat's Habits.

<label> elements display the name of the corresponding field: "Name", "Color", "Age", and "Habits".

The last element of the form is a <button> named Submit. When the user had introduced the pet's info into the input fields, by clicking the Submit button the data in the form should be validated and submitted.

HTML Form

Open the demo to see how the form is rendered. The form doesn't do anything: just displays the input fields.

The next step is to access the input fields values. Let's see how to do that.

2. Form state

The user has introduced data into the input fields: but how do you access these values inside of the React component?

React offers 2 approaches to access the value of an input field: using controlled or uncontrolled components. I prefer controlled components because you read and set the input value through the component's state.

Let's see an example of a controlled component in React:


import { useState } from 'react';

function MyControlledInput({ }) {

const [value, setValue] = useState('');

const onChange = (event) => {

setValue(event.target.value);

};

return (

<>

<div>Input value: {value}</div>

<input value={value} onChange={onChange} />

</>

);

}


Open the demo and type into the input field. You can see that value state variable updates as soon as you type.

The input field is controlled because React sets its value from the state <input value={value} ... />. When the user types into the input field, the onChange handler updates the state with the input’s value accessed from the event object: event.target.value.

The controlled components approach can help you access the value of any input field: being regular textual inputs, textareas, select fields.

Let's control "Register Your Cat" form data by a state variable values:


import { useState } from 'react';

const COLORS = ['white', 'red', 'blue', 'black', 'cream'];

function RegisterYourCatForm() {

const [values, setValues] = useState({

name: '', color: '', age: '', habits: ''

});

const set = name => {

return ({ target: { value } }) => {

setValues(oldValues => ({...oldValues, [name]: value }));

}

};

return (

<form>

<h2>Register Your Cat</h2>

<label>Name*:</label>

<input value={values.name} onChange={set('name')} />

<label>Color*:</label>

<select value={values.color} onChange={set('color')}>

<option value="">Select color</option>

{COLORS.map(c => <option key={c}>{c}</option>)}

</select>

<label>Age*:</label>

<input value={values.age} onChange={set('age')} />

<label>Habits:</label>

<textarea value={values.habits} onChange={set('habits')} />

<button type="submit">Submit</button>

</form>

);

}


values is the state variable that holds the data of the entire form. This is a plain JavaScript object with properties name, color, age, and habits corresponding to each input field in the form.

set(key) is a higher-order function that returns on change handlers. Its purpose is to avoid writing manually on change handlers for each field in the form.

For example, set('name') returns a handler that updates values.name property when a change in the Name field happens.

Open the demo, then type some values into the input fields. values object updates accordingly.

Now you have the form's data stored in the component's state. You can send the form values to the server... but before doing that, how to be sure that the user has introduced all the required information?

You need to perform the form validation.

3. Form validation

I like to use the built-in HTML5 form validation — it is declarative and easy to use.

Using HTML form validation involves marking the input fields with special attributes: for example required marks the input field as required, minlength restricts the minimum length of the text in the field.

Let's mark as required the inputs that are required for completion: Name, Color, and Age.

Then mark the Age field with type="number" and min="0", to be sure that the user introduces here a positive number bigger than 0.

No validation attributes are added to Habits textarea because the field is optional and has no restrictions over the introduced text.

The actual validation happens when the user clicks Submit button. If there are validation errors, they are displayed on the form, and the user can make corrections and click Submit again.


// ...

function RegisterYourCatForm() {

// ...

return (

<form>

<h2>Register Your Cat</h2>

<label>Name*:</label>

<input

type="text" required

value={values.name} onChange={set('name')}

/>

<label>Color*:</label>

<select

required

value={values.color} onChange={set('color')}

>

<option value="">Select color</option>

{COLORS.map(c => <option key={c}>{c}</option>)}

</select>

<label>Age*:</label>

<input

type="number" required min="1"

value={values.age} onChange={set('age')}

/>

<label>Habits:</label>

<textarea value={values.habits} onChange={set('habits')} />

<button type="submit">Submit</button>

</form>

);

}


Now, if you open the demo and click the Submit button, the form is going to be validated.

If, for example, you haven't introduced anything into the Name field and clicked Submit, then the Name field is highlighted with an error message nearby.

Form validation error

4. Form submission

When Submit button is clicked, the browser performs a default form submission by making a full-page POST request to the URL specified in the action attribute of the <form>. If not specified, the action attribute equals the current URL.

But, since the form is controlled by React, you don't want this to happen.

To prevent the browser from performing the default action on submit, simply attach onSubmit event handler to the form, then call event.preventDefault().

Moreover, inside the onSubmit event handler you can perform a POST request by yourself to save the user form:


// ...

function RegisterYourCatForm() {

const [values, setValues] = useState({

name: '', color: '', age: '', habits: ''

});

const saveFormData = async () => {

const response = await fetch('/api/registration', {

method: 'POST',

body: JSON.stringify(values)

});

if (response.status !== 200) {

throw new Error(`Request failed: ${response.status}`);

}

}

const onSubmit = async (event) => {

event.preventDefault(); // Prevent default submission

try {

await saveFormData();

alert('Your registration was successfully submitted!');

setValues({

name: '', color: '', age: '', habits: ''

});

} catch (e) {

alert(`Registration failed! ${e.message}`);

}

}

// ...

return (

<form onSubmit={onSubmit}>

{/* ... */}

</form>

);

}


onSubmit() is an event handler attached to the form submission event <form onSubmit={onSubmit}>. React invokes onSubmit() handler when the form is submitted, i.e. the user clicks Submit button.

If the form validation fails, then onSubmit() event handler is not invoked.

Inside onSubmit(), the async function saveFormData() makes a fetch() POST request to /api/registration. The body of the request contains the serialized form's state variable: JSON.stringify(values).

Open the demo, fill the registration form, and click Submit. The form's values are sent as a POST request to /api/registration URL.

Note that while a client-side validation is performed, you always need to validate the data on the server-side too.

5. Form's initial data

To edit an existing registration, you would need to fill the form with initial data.

Because the input fields values are controlled by values state variable, just initialize the form's state using the initial data:


// ...

function EditRegistrationForm({ registrationId, initialValues }) {

const [values, setValues] = useState(initialValues);

// ...

return (

<form onSubmit={onSubmit}>

{/* ... */}

</form>

);

}


6. Summary

When working with forms in React make the form controlled by a state variable holding the input fields values.

Use the HTML5 built-in form validation. That requires configuring your inputs with corresponding validation attributes, e.g. required to make the input required.

By default, when clicking the form's Submit button, the browser performs a full-page POST request to the URL specified in the action attribute of the <form>. But having the form controlled by React, you can prevent browser's default behavior by attaching an event handler to onSubmit event and calling event.preventDefault().

Also, inside the same onSubmit event handler you can access the form data from the corresponding state variable, and save it manually using your preferred way: by making an async fetch POST request.

Finally, when you'd like to edit an entity using the form, you can load the initial data into your component's form state variable.

What is your preffered approach or library to work with forms in React?