I have a form which consists from several input blocks. The blocks are the same (I mean they all have the same fields set). Each block has an input field name.
On Submit I want to get an object like this:
const resultInput = {
block1: {
name: ''
},
block2: {
name: ''
}
}
I can achieve that with multiple states and on submit combine them into the result object like this:
const [firstBlockInput, setFirstBlockInput] = useState({});
const [secondBlockInput, setSecondBlockInput] = useState({});
const handleChangeFirstBlock = (e) => {
const { name, value } = e.target;
setFirstBlockInput((prev) => ({
...prev,
[name]: value,
}));
};
const handleChangeSecondBlock = (e) => {
const { name, value } = e.target;
setSecondBlockInput((prev) => ({
...prev,
[name]: value,
}));
};
const handleSubmit = () => {
const result = {
block1: firstBlockInput,
block2: secondBlockInput,
};
console.log(result);
};
Also I have to pass these states and onChanges functions down to child form like this:
<SomeForm
onClose={closeForm}
onChangeBlock1={handleChangeFirstBlock}
onChangeBlock2={handleChangeFirstBlock}
firstBlockInputValue={firstBlockInput}
secondBlockInputValue={secondBlockInput}
onSubmit={handleSubmit}
/>
And here's my question. Is there a simple and clean approach to do the same but without extra states and functions (like handleChange
for each input)? Example above is simplified...actually I have three blocks and each has three input fields.
CodePudding user response:
Yes there is a much simpler way if you are fine with a 2D dictionary.
You can provide handleChange
in your <SomeForm>
with a key, and the event. Theoretical example:
const [blockInput, setBlockInput] = useState({});
const handleChange = (key, e) => {
const { name, value } = e.target;
setBlockInput((prev) => ({
...prev,
[key]: {
[name]: value,
}
}));
};
<SomeForm
onChange={handleChange}
/>
Usage example:
<element onChange={(e) => onChange("block1", e)}/>