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.

No responses yet