Field metadata carries more than a name. getInputProps derives the name, the id, the form id, required, the default value, aria-invalid, and the aria-describedby that points at the error message. Passing name="email" by hand gets you one of those seven and drops the rest — and because the field still submits, nothing looks broken. What breaks is invisible: the control no longer announces its error, no longer repopulates after a failed submit, and no longer resets with the form.
Per-field useState is the other half of the same mistake. The form already tracks every value, its dirty state, and its errors; a second copy in component state disagrees with the first the moment anything non-trivial happens — a server-side rejection that should refill the form, a reset, a default arriving from a loader. The bug always surfaces later than the code that caused it.
Conform itself permits the manual form — its docs read fields.email.name and fields.email.initialValue off the metadata directly, and the tutorial only reaches for the helpers at the end, to "minimize the boilerplate" for native inputs. That is the honest status of this rule: manual access is legal Conform, and it is fine as long as you also wire aria-invalid and aria-describedby yourself. This rule exists because that last part is the part everyone skips, and because ui-lib ships components where the wiring is already done.
Thirteen of the library's components ship a Conform-bound variant, chosen because their binding is subtle enough to be worth wrapping (a Select that has to submit through a hidden input, a DatePicker that has to serialise a calendar value). Everything else you bind yourself with getInputProps, or with useInputControl when the control has no native form value. That is not a worse path — it is the same metadata, read explicitly.