14
Strange Bugs 1: The Fussy Controlled Form
In this post I will go over a bug I encountered while creating a controlled form in the app I'm working on.
Here is the layout for the component I was building:
const Card = () => {
const [showFront, setShowFront] = useState(true)
const [formData, setFormData] = useState({
input1: value1,
input2: value2,
...
})
function handleInputChange(e) {
const name = e.target.name;
const value = e.target.value;
setFormData({ ...formData, [name]: value });
}
...
const CardFront = () => {
return <form>
<input name="input1" value={formData.input1}
<input name="input2" value={formData.input2}
...
<button>Submit</button>
</form>
}
const CardBack = () => {
return <div>
<p>{formdata.input1}</p>
<p>{formdata.input2}</p>
...
</div>
}
return (
{ showFront ? <CardFront /> : <CardBack />
)
}
The Bug:
When attempting to type into one of the inputs, I was only able to enter one character, and then I would be tabbed out of the input, and would have to re click the input over and over to continue typing.
The Struggle:
This bug had me stumped for a good few hours, unsure what was causing the issue. After some time, I was convinced there was something going on with the state, as this issue had only came up after I turned the inputs into a controlled form by giving them state.
The Realization:
While taking a look and breaking things down line by line with a fellow peer, we finally discovered what was going on. On each keystroke while typing in one of the inputs, the state for the formData would be updated in the parent / wrapper component, which would re-render the child component, causing it to forget that we we're writing in one of the inputs.
The Solution:
My hack to fix this, was to simply break the nested components out of themselves, and put the jsx into react fragments instead.
return (
{ showFront ?
<>
<form>
<input name="input1" value= {formData.input1}
<input name="input2" value={formData.input2}
...
<button>Submit</button>
</form>
</>
:
<>
<div>
<p>{formdata.input1}</p>
<p>{formdata.input2}</p>
...
</div>
</>
)
14