How to Create Forms and Validate in ReactJS

Rahul Kumar
4 min readMar 18, 2024

--

Form and Validations:

  • Form Interactions and validations are managed by using event and data binding techniques.
  • React uses event and data binding implicity without any additional libraries.
  • React events are Synthetic Events that map to DOM events.
  • React can also use style and class binding for validation styles.

Keyboard Events:

  • onKeyUp
  • onKeyDown
  • onKeyPress

Key Properties:

  • keyCode
  • charCode
  • which
  • shiftKey
  • altKey
  • ctrlKey
  • Users will not be able to enter value in the input field because ReactJS uses unidirectional data flow.

Data flow:

There are 2 two types of Data flow:

  1. Unidirectional
  2. Bidirectional

Bidirectional data flow:

  • Most of the frameworks follow two-way data binding.
  • This would allow for updates from both the end i.e., changes can be done from view to model and vice versa.
  • In this approach state of the model could be mutated by both model and view, it would cause unpredictable data flow.
  • Angular uses bidirectional data flow.

Unidirectional Data flow:

  • In Unidirectional data flow pattern, the changes will be done only from component to view but not vice versa.
  • This would prevent unpredictable data flow and easy to debug.
  • React uses Unidirectional data flow.

There are 3 ways to handle Input or Form in React:

  1. By using Onchange()
  2. Using useRef hook
  3. Using FormData() constructor

Handling Form by using onChange() :

Note: I have used tailwind-css for styling the app.

App.jsx

import "./App.css";
import FormInput2 from "./components/FormInput2";

function App() {
return (
<div className="app">
<form>
<FormInput2 />
</form>
</div>
);
}

export default App;

App.css

.app{
height: 100vh;
width: 100vw;
padding: 0px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 1px solid green;
}

InputForm2.jsx

import { useState } from 'react';
import './formInput.css';

const FormInput2 = () =>{
const [username,setUsername] = useState("");
const [password, setPassword] = useState("");

console.log('Re-Rendered');
//console.log(password);
return(
<div className="form-input">
<input type="text" name="username" id="username" placeholder='username' onChange={e=> setUsername(e.target.value)}/>
<input type="password" name="password" id="password" placeholder='password' onChange={e=> setPassword(e.target.value)}/>
</div>

)
}

export default FormInput2;

form-input.css

.form-input{
padding: 1vw;
height:auto;
width: 20vw;
border: 1px solid red;

}

.form-input input{
width: 15vw;
padding: 0.5vw;
margin: 0.5vw;
}

useRef():

InputForm3.jsx

import { useRef, useState } from "react";
import "./formInput.css";

const FormInput3 = () => {

const usernameRef = useRef();

console.log('re-rendered');

const handleSubmit = (e) =>{
e.preventDefault();
console.log(usernameRef.current.value); // You will get username value at console
}

return (
<div className="form-input">
<form onSubmit={handleSubmit}>
<input
type="text"
name="username"
id="username"
placeholder="username"
ref={usernameRef}
/>
<input
type="password"
name="password"
id="password"
placeholder="password"

/>

<button>Submit</button>
</form>
</div>
);
};

export default FormInput3;

App.jsx

import "./App.css";
import FormInput3 from "./components/FormInput3";

function App() {
return (
<div className="app">
<FormInput3 />
</div>
);
}

export default App;

By FormData :

FormInput4.jsx

import { useRef, useState } from "react";
import "./formInput.css";

const FormInput4 = () => {

console.log('re-rendered');

const handleSubmit = (e) =>{
e.preventDefault();
const data = new FormData(e.target);
console.log(Object.fromEntries(data.entries()));
}

return (
<div className="form-input">
<form onSubmit={handleSubmit}>
<input
type="text"
name="username"
id="username"
placeholder="username"
/>
<input
type="password"
name="password"
id="password"
placeholder="password"
/>

<button>Submit</button>
</form>
</div>
);
};

export default FormInput4;

App.jsx

import "./App.css";
import FormInput4 from "./components/FormInput3";

function App() {
return (
<div className="app">
<FormInput4 />
</div>
);
}

export default App;

How to control multiple inputs:

Example 1:

FormByControlledComponent.jsx

import React, { useState } from "react";

const FormByControlledComponent = () => {
const [val, setVal] = useState({ name: "", email: "" });

const handleSubmit = (event) => {
event.preventDefault();
console.log(val);;
};

return (
<div className="w-full h-screen bg-zinc-100 flex flex-col justify-center items-center">
<h1 className="font-bold text-3xl underline">
Form by Controlled Components
</h1>
<form className="w-full mt-5 p-4" onSubmit={handleSubmit}>
<input
type="text"
name="name"
id="name"
placeholder="name"
className="border-2 mr-2 rounded"
onChange={(event) => setVal({ ...val, name: event.target.value })}
/>
<input
type="text"
name="email"
id="email"
placeholder="email"
className="border-2 mr-2 rounded"
onChange={(event) => setVal({ ...val, email: event.target.value })}
/>
<input
type="submit"
className="border-2 rounded-md bg-orange-500 px-2 py-1 text-white"
/>
</form>
</div>
);
};

export default FormByControlledComponent;

App.jsx

import { useState } from 'react'
import './App.css'

import FormByControlledComponent from './components/FormByControlledComponent'

function App() {


return (
<div className='w-full h-screen bg-blue-200'>
<FormByControlledComponent />
</div>
)
}

export default App

Example 2:

import React, { useRef } from 'react'

const Form = () => {
const name = useRef(null);
const email = useRef(null);

const handleSubmit = (event) =>{
event.preventDefault();
console.log(name.current.value);
console.log(email.current.value);
}

return (
<div className='flex flex-col justify-center items-center'>
<h1 className='font-bold text-3xl underline'>Form by useRef() hook</h1>
<form className='w-full mt-5 p-4' onSubmit={handleSubmit}>
<input ref={name} type="text" name="name" id="name" placeholder="name" className='border-2 mr-2 rounded'/>
<input ref={email} type="text" name="email" id="email" placeholder="email" className='border-2 mr-2 rounded' />
<input type="submit" className='border-2 rounded-md bg-orange-500 px-2 py-1 text-white' />
</form>
</div>
)
}

export default Form;

App.jsx


import './App.css'

import Form from './components/Form'

function App() {


return (
<div className='w-full h-screen bg-blue-200'>
<Form />
</div>
)
}

export default App

On both of the example, we are handling multiple inputs.

Thanks…

--

--

Rahul Kumar
Rahul Kumar

Written by Rahul Kumar

MERN Stack Developer building scalable web apps with MongoDB, Express.js, React, and Node.js. Sharing insights and best practices for modern web development.