im currently trying to create an dynamic form that uses a sub component to render out some input fields as createing them static would exceed a limit. I pass the states for the the form i made aswell as some date and the change form. But when i render the form as it does so fine! as soon as i change the state its sends a warning about uncontrolled components that you can read about it here
I have tried pre-setting all the fields with empty defaults but it doesnt help.
Am i doing it somewhat correct or totally wrong? or what is the correct way, or what am i doing wrong. thanks in adbance.
As for the code looks like this:
Edit.js
export default function InventoryItemEdit() {
const [form, setForm] = useState({});
function handleFormChange(e) {
setForm({ ...form, [e.target.name]: e.target.value });
}
const variants = (
<ItemVariants
form={form}
onChange={handleFormChange}
fields={form.sizes}
/* ^^ fields data fetched from the server i set via use effect hook when loading the page */
/>
);
const updateItem = async (event) => {
event.preventDefault();
/* Do form submit post */
};
return (
<form onSubmit={updateItem}>
<div>
<p htmlFor="name">Name</p>
<input
id="name"
name="name"
onChange={handleFormChange}
value={form.name}
type="text"
required
placeholder="Name of Item"
/>
</div>
{variants}
</form>
);
}
As for the sub component ItemVariants it looke like this
ItemVariants.js
export default function ItemVariants({
form = {},
onChange = '',
fields = [],
}) {
return (
<>
{fields.map((row, index) => (
<div>
<span>
{row.name}
</span>
<input
type="text"
id={`variant${index}`}
name={`variant${index}`}
onChange={onChange}
value={form[`variant${index}`]}
required
min="0"
placeholder="0"
defaultValue="0"
/>
</div>
))}
</>
);
}
Answer to your bug: I see that everything is okay, but the only issue is that you didn't set the initial state with the name key. Thats an analysing issue because in your code you doing [e.target.name]:e.target.value and the way inputs works generally is that event is triggered but must recent value is emitted when the event happens next. it works like a++.
Do this:
const [form, setForm] = React.useState({ name: '' });
The general rule of thumb is that always describe your form input keys when your inputs are predefine and not dynamic(in this case your name input is predefined).
So After digging reading this post i have to thank! @juliomalves for solution with value={form[`variant${index}`] ?? ''} or value={form[`variant${index}`] || ''}
I also found out i was accidently adding defaultvalue aswell as value which cannot be set at the same time i found out. After i tested it removed the default value and set it correctly to be a string! it now works like a charm! Also thanks to @Emmanuel Onah for the explaination it really helped me understand more about the react states!
Thanks again for everyone that helped