I am creating an app that allows users to dynamically create new form fields. When making a new field, I ran into a bug where, when React re-renders my mapped over user input array, the form data was not re-rendered so the forms appeared blank. I realized this was because I did not set the value attributes for my input but after I set them I could no longer type in the input.
The state:
interface FieldObject {
fieldName: string;
fieldValue: string;
}
class FieldObject {
constructor(fieldName: string, fieldValue: string) {
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
}
const [userInput, setUserInput] = useState([new FieldObject("", "")]);
The map function:
{userInput.map((element, index) => (
<InputGroup
key={uuidv4()}
id={index}
onChange={(e: React.ChangeEvent) => onChange(e, index)}
onClick={(e: React.MouseEvent<HTMLButtonElement>) =>
removeField(e, index)
}
inputValue={element.fieldName || ""}
textAreaValue={element.fieldValue || ""}
/>
))}
The input group component:
return (
<div>
<TextInput
id={id.toString()}
label="Field Name"
placeholder="Cat Sounds"
name="fieldName"
onChange={onChange}
value={inputValue}
/>
<TextField
id={id.toString()}
label="Field Value"
placeholder="meow purr"
onChange={onChange}
name="fieldValue"
value={textAreaValue}
/>
<button onClick={onClick}>Remove</button>
</div>
);
The onChange handler:
function onChange(e: React.ChangeEvent, index: number) {
const target = e.target;
const newUserInput: Array<FieldObject> = userInput;
newUserInput[index][target.name] = target.value;
setUserInput(newUserInput);
}
The input:
<input
className="block text-base px-2 pt-2 pb-1 bg-black border-b-2 border-b-slate-700 focus:border-b-white focus:outline-1 focus:outline-offset-8 shadow-lg transition-all"
id={id}
type="text"
placeholder={placeholder}
value={value}
onChange={onChange}
name={name}
></input>
I have tried looking around online but most of the similar issues seem to have been fixed with a spelling change. My onChange still console logs but it the console logs show only one character being tracked as changed. Also when the page hot reloads it will render that stored character in the correct input.
Changing value to defaultValue works but I don’t know if that is best practice.