Home > Mobile >  How to get user input as a nested object?
How to get user input as a nested object?

Time:08-07

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)}/>
  • Related