Format Phone Number with React
This article addresses the problem of formatting phone number inputs into a given format (555) 123-1234
using React.
You can take a look on this demo.
Firstly, we'll create our component and import it into the App.tsx
file.
// App.tsx file
import "./App.css";
import PhoneNumberInput from "./components/PhoneNumberInput";
function App() {
return <PhoneNumberInput />;
}
export default App;
The PhoneNumberInput
component:
// PhoneNumberInput component
import { useState } from "react";
import { enforceFormat, formatToPhone } from "./helpers";
const PhoneNumberInput = () => {
const [phoneValue, setPhoneValue] = useState<string | undefined>("");
return (
<input
type="text"
maxLength={16}
onKeyDown={enforceFormat}
onChange={(event) => setPhoneValue(formatToPhone(event))}
value={phoneValue}
/>
);
};
export default PhoneNumberInput;
For the format of the input, we have 2 handler functions: enforceFormat
and formatToPhone
The first function enforceFormat
, prevents any non-numeric and non-essential keys from affecting the input, ensuring that the user can only enter valid phone number characters and use necessary editing shortcuts.
isNumericInput
function checks if the pressed key is a numeric digit, allowing only numbers to be entered.isModifierKey
function identifies and permits essential keys such as Shift, Backspace, Tab, Enter, Delete, arrow keys, and common shortcut keys (e.g., Ctrl+A, Ctrl+C).
// helpers.ts file
import { ChangeEvent, KeyboardEvent } from "react";
export const isNumericInput = (event: KeyboardEvent<HTMLInputElement>) => {
const code = event.code;
return (
code === "Digit1" ||
code === "Digit2" ||
code === "Digit3" ||
code === "Digit4" ||
code === "Digit5" ||
code === "Digit6" ||
code === "Digit7" ||
code === "Digit8" ||
code === "Digit9" ||
code === "Digit0"
);
};
export const isModifierKey = (event: KeyboardEvent<HTMLInputElement>) => {
const code = event.code;
return (
event.shiftKey === true ||
code === "Backspace" ||
code === "ShiftRight" ||
code === "ShiftLeft" ||
code === "Tab" ||
code === "Enter" ||
code === "Delete" || // Allow Shift, Backspace, Tab, Enter, Delete
code === "ArrowRight" ||
code === "ArrowLeft" ||
// Allow Ctrl/Command + A,C,V,X,Z
((event.ctrlKey === true || event.metaKey === true) &&
(code === "KeyA" ||
code === "KeyC" ||
code === "KeyV" ||
code === "KeyX" ||
code === "KeyZ"))
);
};
export const enforceFormat = (event: KeyboardEvent<HTMLInputElement>) => {
if (!isModifierKey(event) && !isNumericInput(event)) {
event.preventDefault();
}
};
The formatToPhone
function is designed to transform user input into a standardized phone number format.
It begins by stripping all non-numeric characters from the input and limiting the input to the first ten digits, which are sufficient for a standard U.S. phone number.
The function then divides these digits into three parts: areaCode
, the middle
three digits, and the last
four digits. Depending on the number of digits entered, the function assembles and returns a formatted phone number string in the form (555) 123-1234
.
// helpers.ts file
export const formatToPhone = (event: ChangeEvent<HTMLInputElement>) => {
const input = event.target.value.replace(/\D/g, "").substring(0, 10); // First ten digits of input only
const areaCode = input.substring(0, 3);
const middle = input.substring(3, 6);
const last = input.substring(6, 10);
let phoneNumber = "";
if (input.length > 6) {
phoneNumber = `(${areaCode}) ${middle} - ${last}`;
} else if (input.length > 3) {
phoneNumber = `(${areaCode}) ${middle}`;
} else if (input.length > 0) {
phoneNumber = `(${areaCode}`;
}
return phoneNumber;
};
And just like that, you've turned a string of chaotic digits into a well-behaved, properly formatted phone number!