Let’s say you want users to input their SSN in your UI, so you create a React component and give it a nice name, something like <SsnInput />.

import React from "react"
import ReactDOM from "react-dom"

function SsnInput() {
  const [state, setState] = React.useState("")
  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    setState(e.target.value)
  }
  return <input value={state} onChange={handleChange} />
}

ReactDOM.render(
  <React.StrictMode>
    <SsnInput />
  </React.StrictMode>,
  document.getElementById("root")
)

Then you think, we really only want digits in the social security number so let’s use type="number":

diff --git a/src/index.tsx b/src/index.tsx
index b35e8a7..aaddd35 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -6,7 +6,7 @@ function SsnInput() {
   function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
     setState(e.target.value)
   }
-  return <input value={state} onChange={handleChange} />
+  return <input value={state} onChange={handleChange} type="number" />
 }

 ReactDOM.render(

But now there is a problem. Users can input their social security numbers, but once they add a dash -, the input stops working and defaults to an empty string.

Turns out this is a known issue with type="number" and <input />, which we can reproduce in plain JS:

const input = document.createElement("input")
input.type = "number"
input.value = ""
input.oninput = e => {
  input.value = e.target.value
}
document.getElementById("root").appendChild(input)

TL;DR: Using type="number" is risky business

Also, there’s a related issue for React, but as we’ve seen, this buggy UX is caused by the fundamental behavior of <input type="number" />.