JavaScript How to save input entered by the user in a state which is an array in React

The whole idea is to take users input in a form and display their input in a JSON object. In state I have an array and inside it another array.

My Form.js looks like this,

state= {
    groups:[{
      typeA:[{}],
      typeB:[{}]
    }],
    credentials: false
    };

    change = e =>{
        this.setState({[e.target.name]: e.target.value})
    };

    handleSubmit(event) {
        event.preventDefault();
        this.setState({
          credentials: true 
        });
      }
render(){
        return(
            <div class="classform">
            <form >
                <label>
                    Field1:
                    <br/>
                    <input type="text"
                    name="typeA"
                    placeholder="Type A"
   //store it as the first element of the type A
                    value={this.state.groups.typeA[0]} 
                    onChange={this.change.bind(this)}
                 />
  //other fields with the same code

Subsequently, Field2 will be stored as the second element of type A Then, Field3 and Field4 will be stored as 2 of type B array

I expect the code to give me an output like :

"typeA": ["field1 value", "field2 value"],
"typeB": ["field3 value", "field4 value"]}

I'm a beginner with React and I'm not able to store the field values in the state which is an array.

Answer:1

Give each input a custom attribute, for example data-group="typeA". In your on change function get that value and add the values to the correct array.

<input
  type="text"
  name="col2"
  placeholder="Type A"
  data-group="typeA" // add custom attribute typeA | typeB etc.
  onChange={e => this.change(e)}
/>

In your change handle get the custom attribute, and use it to add the value to the correct array.

change = e => {

  // create a copy of  this.state.groups
  const copyGroups = JSON.parse(JSON.stringify(this.state.groups));

  // get data-group value
  const group = event.target.dataset.group;

  if (!copyGroups[0][group]) {
    copyGroups[0][group] = []; // add type if it doesn't exists
  }

  const groups = copyGroups[0][group];
  const index = this.findFieldIndex(groups, e.target.name);

  if (index < 0) {
    // if input doesn't exists add to the array
    copyGroups[0][group] = [...groups, { [e.target.name]: e.target.value }];
  } else {
    // else update the value
    copyGroups[0][group][index][e.target.name] = e.target.value;
  }

  this.setState({ groups: copyGroups });
};

pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script type="text/babel">

function formatState(json) {
  if (typeof json != 'string') {
       json = JSON.stringify(json, undefined, 2);
  }
  json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, (match) => match);
}

const Credentials = ({ value }) => {
  return <pre>{formatState(value)}</pre>;
};

class App extends React.Component {
  state = {
    groups: [
      {
        typeA: [],
        typeB: []
      }
    ],
    credentials: false
  };

  handleSubmit = event => {
    event.preventDefault();

    this.setState({
      credentials: true // display Credentials  component
    });
  };

  // get the current input index in the array typeA | typeB
  findFieldIndex = (array, name) => {
    return array.findIndex(item => item[name] !== undefined);
  };

    change = e => {

      // create a copy of  this.state.groups
      const copyGroups = JSON.parse(JSON.stringify(this.state.groups));

      // get data-group value
      const group = event.target.dataset.group;
      
      if (!copyGroups[0][group]) {
        copyGroups[0][group] = []; // add new type
      }
      
      const groups = copyGroups[0][group];
      const index = this.findFieldIndex(groups, e.target.name);

      if (index < 0) {
        // if input doesn't exists add to the array
        copyGroups[0][group] = [...groups, { [e.target.name]: e.target.value }];
      } else {
        // update the value
        copyGroups[0][group][index][e.target.name] = e.target.value;
      }

      this.setState({ groups: copyGroups });
    };
    
 removeKey = (key) => {
    const temp = {...this.state};
    delete temp[key];
    return temp;
 }

  render() {
    return (
      <div>
        <input
          type="text"
          name="col1"
          placeholder="Type A"
          data-group="typeA"
          onChange={e => this.change(e)}
        />

        <input
          type="text"
          name="col2"
          placeholder="Type A"
          data-group="typeA"
          onChange={e => this.change(e)}
        />

        <input
          type="text"
          name="col2"
          placeholder="Type B"
          data-group="typeB"
          onChange={e => this.change(e)}
        />
        
        <input
          type="text"
          name="typec"
          placeholder="Type C | New Type"
          data-group="typeC"
          onChange={e => this.change(e)}
        />
        
        <input
          type="text"
          name="typed"
          placeholder="Type D | New Type"
          data-group="typeD"
          onChange={e => this.change(e)}
        />

        <button onClick={this.handleSubmit}>Submit</button>
        {this.state.credentials && (
          <Credentials value={JSON.stringify(this.removeKey('credentials'), undefined, 2)} />
        )}
      </div>
    );
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
</script>
Answer:2

For the sake of simplicity, I will recommend below solution, Instead of having a nested array in the state, you can manage the input values in the different state variables and at the time of submitting, change them to the output you want.

state = {
  field1: '',
  field2: '',
  field3: '',
  field4: '',
}
change = e => {
  this.setState({[e.target.name]: e.target.value})
};

handleSubmit(event) {
  event.preventDefault();
  const { field1, field2, field3, field4 } = this.state;
  // This is your output
  const output = [{typeA: [field1, field2], typeB: [field2, field3]}];
  this.setState({
    credentials: true 
  });
}
render(){
  return(
    <div class="classform">
      <form >
        <label>
          Field1:
          <br/>
          <input type="text"
            name="field1"
            placeholder="Type A"
            value={this.state.field1}
            onChange={this.change}
          />
        </label>
        <label>
          Field2:
          <br/>
          <input type="text"
            name="field2"
            placeholder="Type A"
            value={this.state.field2}
            onChange={this.change}
          />
        </label>
Answer:3

In componentDidMount I'm trying to get data called topic from /api/topics/${params.TopicId route then from response I want to send only topic.user_id to another route and get whole user as response. ...

In componentDidMount I'm trying to get data called topic from /api/topics/${params.TopicId route then from response I want to send only topic.user_id to another route and get whole user as response. ...

  1. getting data from api
  2. getting data from firestore
  3. getting data from twitter
  4. getting data from a dead phone
  5. getting data from old hard drive
  6. getting data from json
  7. getting data from firebase
  8. getting data from android to iphone
  9. getting data from another sheet in excel
  10. getting data from google analytics
  11. getting data from excel in python
  12. getting data from figure matlab
  13. getting data from instagram
  14. getting data from api python
  15. getting data from broken iphone
  16. getting data from json javascript
  17. getting data from a dead computer
  18. getting data from multiple tables sql
  19. getting data from snapchat
  20. getting data from api react

These are the geometries: http://p5js.org/examples/examples/3D_Geometries.php I've already tried the syntax for the 2d shapes but it doesn't appear to work. Is there a special syntax for the WEBGL ...

These are the geometries: http://p5js.org/examples/examples/3D_Geometries.php I've already tried the syntax for the 2d shapes but it doesn't appear to work. Is there a special syntax for the WEBGL ...

Today I wrote code for some programming contest. When I run it I was surprised because of error. Cannot read property 'forEach' of undefined in a place where looks like "error free space". sum = 0 ...

Today I wrote code for some programming contest. When I run it I was surprised because of error. Cannot read property 'forEach' of undefined in a place where looks like "error free space". sum = 0 ...

WHAT I WANT TO DO I want to shorten my code. This Drum Play App plays sound by pressing certain keys or clicking with your mouse. It works, but the code for click events is too long because I ...

WHAT I WANT TO DO I want to shorten my code. This Drum Play App plays sound by pressing certain keys or clicking with your mouse. It works, but the code for click events is too long because I ...

  1. short code with
  2. short code with twilio
  3. shorten code in python
  4. shorten code in excel