違いは、input の値の source of truth が誰かです。React state なのか、DOM 自体なのか、という点です。
Controlled(React が値を所有する)
input の value は state によって決まり、onChange が state を同期します。DOM は常に React を反映します。
jsx
[name, setName] = ();
state が source of truth なので、キー入力ごとに validate、format、transform できます(例: 大文字に強制する、長さを制限する、submit button を disable する)。
値はブラウザが保持し、必要なときだけ ref 経由で読み取ります。
const inputRef = useRef(null);
<input defaultValue="" ref={inputRef} />;
// submit 時: const value = inputRef.current.value;
<input type="file"> は常に uncontrolled)、または non-React widget との統合。コードは少なくなりますが、変化が起きた瞬間に反応することはできません。両方を混ぜる(value と defaultValue の両方を渡す)のはよくある間違いで、React warning の原因になります。