0

How can I get nested form elements values in ReactJS?

Example

Let say I have a form with following elements:

<form onSubmit={handleSubmit(e)}>
  <input ref="name" type="text" />
  { /* possibly unlimited number of emails */ }
  <input ref="email[]" type="text" />
  <input ref="email[]" type="text" />
  { /* possibly unlimited number of book objects */ }
  <fieldset>
    <input ref="title" type="text" />
    <input ref="author" type="text" />
  </fieldset>
  <fieldset>
    <input ref="title" type="text" />
    <input ref="author" type="text" />
  </fieldset>
</form>

I want to get values of these fields onSubmit. The easiest way and most intuitive would be through:

this.refs

But it will flatten all refs and return only last of the array elements. So it will return something like:

{ name: '', email[]: '', title: '', author: '' }

What I want to get should look like this:

{ name: '',
  email:['', ''],
  books: [
    { title: '', author: '' },
    { title: '', author: '' }
  ]
}

Or something similar.

Maybe using refs is not the best option, but I'm not sure about any other alternatives.

EDIT Executing:

e.target.childNodes

Returns something similar to what I want to achieve but it returns plain HTML nodes so getting values out of them is quite a lot of work (writing some custom method for processing nodes tree).

1 Answer 1

2

If the input would have some kind of ID or a key, you could probably do:

<input key="[YOUR_KEY]" type="text" onChange={ (e) => { this.setState({
    [YOUR_KEY]: e.currentTarget.value
}); } } />

And then you could reference all the values directly from the state.

The key can even be arbitrary as an incremental number:

<input key="email_1" type="text" onChange={ (e) => { this.setState({ email_1: e.currentTarget.value }); } } />
<input key="email_2" type="text" onChange={ (e) => { this.setState({ email_2: e.currentTarget.value }); } } />
<input key="email_3" type="text" onChange={ (e) => { this.setState({ email_3: e.currentTarget.value }); } } />
<input key="email_4" type="text" onChange={ (e) => { this.setState({ email_4: e.currentTarget.value }); } } />

Then, you can reference the second email field for example with this.state.email_2.

Sign up to request clarification or add additional context in comments.

6 Comments

I will use redux store as a model for my form but I don't want to update app state on each change. I think it should be somehow possible to get all the values only on submit.
You can use redux, and still use this methodology. When you update your redux store, instead of reading the data from ref, read it from the component's state.
I know it will work with Redux. This is my current solution but I'm looking for the way of retrieving values directly without need to keep it in sync with the store.
This is what I'm saying, you don't have to keep it in sync with the store! You only keep it in sync with the specific component's state. When you finally decide to update the store (user has submitted the form or whatever), then all the data is available in the state and the store can be updated with a single action.
OK. I didn't get it. Thanks for the explanation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.