4. Two way Binding #
Created Monday 07 February 2022
Why #
In forms, we usually need to save the state to then do a PUT/PATCH call to the server asynchronously. This is easily done using useState
. But how do we reset inputs to their default value (or blank).
Binding state to change in input tag is one-way binding. But we can also bind the input attribute value
to the state. This way, when we clear the state (programmatically), the inputs are also reset (in UI), on submission. This is a two way binding. And it’s mostly used in forms.
How #
Here’s a component that uses two way binding:
import React, { useState } from "react";
import "./ExpenseForm.css";
function ExpenseForm() {
const [enteredTitle, setEnteredTitle] = useState("");
const [enteredAmount, setEnteredAmount] = useState("");
const [enteredDate, setEnteredDate] = useState("");
const titleChangeHandler = (event) => {
setEnteredTitle(event.target.value);
};
const amountChangeHandler = (event) => {
setEnteredAmount(event.target.value);
};
const dateChangeHandler = (event) => {
setEnteredDate(event.target.value);
};
const submitHandler = (event) => {
// this is called when submit is clicked
event.preventDefault(); // prevent default submit
// entered data is saved
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate),
};
console.log(expenseData);
// clearing/restting the input fields
setEnteredTitle("");
setEnteredAmount("");
setEnteredDate("");
};
return (
<form action="POST" onSubmit={submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label htmlFor="title">Title</label>
<input
type="text"
name="title"
value={enteredTitle} // for two way binding
onChange={titleChangeHandler}
/>
</div>
<div className="new-expense__control">
<label htmlFor="amount">Amount</label>
<input
type="number"
name="amount"
min="0.01"
step="0.01"
value={enteredAmount} // for two way binding
onChange={amountChangeHandler}
/>
</div>
<div className="new-expense__control">
<label htmlFor="date">Date</label>
<input
type="date"
name="date"
min="2019-01-01"
max="2022-12-31"
value={enteredDate} // for two way binding
onChange={dateChangeHandler}
/>
</div>
</div>
<div className="new-expense__actions">
<button type="submit">Add Expense</button>
</div>
</form>
);
}
export default ExpenseForm;
As said, it’s quite useful in forms.
What #
To add two way binding, create a state and use both the value and state updater function (as onchange) on the UI element.
const [name, setName] = useState('');
// setName -> changes value and re-renders -> new UI has new `value` prop. Ok
// User event -> triggers onchange -> changes value and re-renders -> new UI has new `value` prop. Ok
// i.e. 2 way binding achieved
return <input value={name} onChange={(e) => setName(e.target.value)} />;