title: React js useState hook. How to update state of a json object with an a array in it when a checkbox is clicked
body: <p>I am sending my state as a  <code>stringified</code> variable from a form to a POST request through a lamda server which then parses it and sends it to sendgrid which there I am using send grids templating feature. Which requires me to have json Formatted like this in order to loop over one particular part (multiple checkboxes) which all should have the same key but a different value, set by a <code>reason="Weight Loss"</code> in the form. Here is how the eventual json needs to be formed.</p>
  
  <pre><code>{
    "name" :"anders",
    "message" : "winfsdafasfdsfsadfsadnipeg",
    "package" : "silver",
    "email" : "email@email.com",
    "subject" : "fdsafas",
    "data":{
        "reasonArray":[
           {
              "reason":"weightLoss"
           },
           {
              "reason":"Sport"
           }
        ]
     }
  }
  </code></pre>
  
  <p>Then I can do some magic and loop over the reason's that were checked in the checkbox</p>
  
  <pre><code>&lt;ol&gt;
    {{#each data.reasonArray}}
      &lt;li&gt;{{this.reason}} &lt;/li&gt;
    {{/each}}
  &lt;/ol&gt;
  </code></pre>
  
  <p>Now I had it working if I left the state with single key value pairs and don't have the <code>data</code> portion.
  Here is what my initial state looked like working.</p>
  
  <pre><code>const [formState, setFormState] = React.useState({
      name: "",
      package: `${data.datoCmsPricing.title}`,
      email: "",
      subject: "",
      weightLoss:"",
      strength:"",
      sport:"",
      message: "",
    })
  </code></pre>
  
  <p>I then had the following <code>onChange</code> event that set the state with the name of the input field as the key and the value or checked state as the value. Seen here</p>
  
  <pre><code>const onChange = (e) =&gt; {
      if (e.target.type === 'checkbox' &amp;&amp; !e.target.checked) {
          setFormState({...formState, [e.target.name]: e.target.checked});
      } else {
          setFormState({...formState, [e.target.name]: e.target.value });
      }
   }
  </code></pre>
  
  <p>and here is my form</p>
  
  <pre><code>&lt;form onSubmit={submitForm}&gt;
        {/* &lt;input type="text" name="package" value={data.datoCmsPricing.title} /&gt; */}
        &lt;label&gt;
          Name
          &lt;input
            type="text"
            name="name"
            value={formState.name}
            onChange={onChange}
          /&gt;
        &lt;/label&gt;
        &lt;label&gt;
          Email
          &lt;input
            type="email"
            name="email"
            value={formState.email}
            onChange={onChange}
          /&gt;
        &lt;/label&gt;
        &lt;label&gt;
          Subject
          &lt;input
            type="text"
            name="subject"
            value={formState.subject}
            onChange={onChange}
          /&gt;
        &lt;/label&gt;
        &lt;div&gt;
          &lt;h3&gt;Reasons for wanting to train&lt;/h3&gt;
          &lt;label&gt;
          Weight Loss
          &lt;input 
            type="checkbox"
            name="weightLoss"
            checked={formState.weightLoss}
            onChange={onChange}
          /&gt;
          &lt;/label&gt;
          &lt;label&gt;
          Strength 
          &lt;input 
            type="checkbox"
            name="strength"
            checked={formState.strength}
            onChange={onChange}
          /&gt;
          &lt;/label&gt;
          &lt;label&gt;
          Sport 
          &lt;input 
            type="checkbox"
            name="sport"
            checked={formState.sport}
            onChange={onChange}
          /&gt;
          &lt;/label&gt;
        &lt;/div&gt;
  
        &lt;label&gt;
          message
          &lt;textarea
            name="message"
            value={formState.message}
            onChange={onChange}
          /&gt;
        &lt;/label&gt;
        &lt;button type="submit"&gt;Submit&lt;/button&gt;
      &lt;/form&gt;
  </code></pre>
  
  <p>I then send it off to my lamdba function</p>
  
  <pre><code>  const response = await fetch("/.netlify/functions/sendmail", {
         method: "POST",
         body: JSON.stringify(formState),
       })
  </code></pre>
  
  <p>Now my state looks like the following in json after being sent to lamdbda function and being parsed</p>
  
  <pre><code>{ 
    name: 'Anders',
    package: 'silver',
    email: 'email@email.com',
    subject: 'fdsafa',
    weightLoss: 'on',
    strength: 'on',
    sport: 'on',
    message: 'fdsafasf'
  } 
  </code></pre>
  
  <p>Now I want to have my initial state to look like the format that sendgird wants it in, so this is what I attempted with my state setup.</p>
  
  <pre><code>const [formState, setFormState] = React.useState({
      name: "",
      package: `${data.datoCmsPricing.title}`,
      email: "",
      subject: "",
      weightLoss:"",
      strength:"",
      sport:"",
      message: "",
      data:{
        reasonArray:[
          {
            reason:""
          },
          {
            reason:""
          }
        ]
      }
    })
  </code></pre>
  
  <p>Then I tried to update the onChange event for the checked values with the following, I also update my form so it grabs a user friendly name for the reason. Seen below this code</p>
  
  <pre><code> const onChange = (e) =&gt; {
      if (e.target.type === 'checkbox' &amp;&amp; !e.target.checked) {
          setFormState({...formState, data:{ reasonArray:[ { reason:e.target.reason}, ]}});
      } 
      ...
   }
  </code></pre>
  
  <p>Form Changes</p>
  
  <pre><code>  ...
       &lt;label&gt;
          Weight Loss
          &lt;input 
            type="checkbox"
            name="weightLoss"
            reason="weightLoss"
            checked={formState.weightLoss}
            onChange={onChange}
          /&gt;
          &lt;/label&gt;
          &lt;label&gt;
          Strength 
          &lt;input 
            type="checkbox"
            name="strength"
            reason="strength"
            checked={formState.strength}
            onChange={onChange}
          /&gt;
          &lt;/label&gt;
          &lt;label&gt;
          Sport 
          &lt;input 
            type="checkbox"
            name="sport"
            reason="sport"
            checked={formState.sport}
            onChange={onChange}
          /&gt;
          &lt;/label&gt;
     ...
  </code></pre>
  
  <p>The resulting Json I get after the Post request is this, with my attempt. It does not update the data part. So the resulting Json is in the right format, but it doesn't have the reason's attached. Thanks ahead of time for any help.</p>
  
  <pre><code>{ 
     "name":"Anders",
     "package":"Silver",
     "email":"email@email.com",
     "subject":"fdsaf",
     "weightLoss":"on",
     "strength":"on",
     "sport":"on",
     "message":"fdsafas",
     "data":{ 
        "reasonArray":[ 
           { 
              "reason":""
           },
           { 
              "reason":""
           }
        ]
     }
  }
  </code></pre>
  
  <p>Attempting Rabi's answer</p>
  
  <pre><code>  ...
  
   const prepareDataForApi = (formData) =&gt; {
    const newFormData = Object.assign({}, formData); // optional if passed cloned copy of formData object or you can also use lodash cloneDeep
    newFormData.data = {
      reasonArray:[]
    };
  
    Object.keys(newFormData.reasons).forEach(key =&gt; {
      if(newFormData.reasons[key]){
        newFormData.data.reasonArray.push({reason: key})
      }
    });
  
    delete newFormData.reasons;
  
    return newFormData;
  }
  
  
  
   const submitForm = async (e) =&gt; {
    e.preventDefault();
  
    setForm(false);
  
  
  
    // const newFormData = prepareDataForApi(formData); 
       const newFormData = prepareDataForApi(formState);
  
    console.log(newFormData);
  
  ...
  </code></pre>