Quantcast
Channel: Active questions tagged javascript - Stack Overflow
Viewing all articles
Browse latest Browse all 138192

React js useState hook. How to update state of a json object with an a array in it when a checkbox is clicked

$
0
0

I am sending my state as a stringified 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 reason="Weight Loss" in the form. Here is how the eventual json needs to be formed.

{
  "name" :"anders",
  "message" : "winfsdafasfdsfsadfsadnipeg",
  "package" : "silver",
  "email" : "email@email.com",
  "subject" : "fdsafas",
  "data":{
      "reasonArray":[
         {
            "reason":"weightLoss"
         },
         {
            "reason":"Sport"
         }
      ]
   }
}

Then I can do some magic and loop over the reason's that were checked in the checkbox

<ol>
  {{#each data.reasonArray}}
    <li>{{this.reason}} </li>
  {{/each}}
</ol>

Now I had it working if I left the state with single key value pairs and don't have the data portion. Here is what my initial state looked like working.

const [formState, setFormState] = React.useState({
    name: "",
    package: `${data.datoCmsPricing.title}`,
    email: "",
    subject: "",
    weightLoss:"",
    strength:"",
    sport:"",
    message: "",
  })

I then had the following onChange 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

const onChange = (e) => {
    if (e.target.type === 'checkbox'&& !e.target.checked) {
        setFormState({...formState, [e.target.name]: e.target.checked});
    } else {
        setFormState({...formState, [e.target.name]: e.target.value });
    }
 }

and here is my form

<form onSubmit={submitForm}>
      {/* <input type="text" name="package" value={data.datoCmsPricing.title} /> */}
      <label>
        Name
        <input
          type="text"
          name="name"
          value={formState.name}
          onChange={onChange}
        />
      </label>
      <label>
        Email
        <input
          type="email"
          name="email"
          value={formState.email}
          onChange={onChange}
        />
      </label>
      <label>
        Subject
        <input
          type="text"
          name="subject"
          value={formState.subject}
          onChange={onChange}
        />
      </label>
      <div>
        <h3>Reasons for wanting to train</h3>
        <label>
        Weight Loss
        <input 
          type="checkbox"
          name="weightLoss"
          checked={formState.weightLoss}
          onChange={onChange}
        />
        </label>
        <label>
        Strength 
        <input 
          type="checkbox"
          name="strength"
          checked={formState.strength}
          onChange={onChange}
        />
        </label>
        <label>
        Sport 
        <input 
          type="checkbox"
          name="sport"
          checked={formState.sport}
          onChange={onChange}
        />
        </label>
      </div>

      <label>
        message
        <textarea
          name="message"
          value={formState.message}
          onChange={onChange}
        />
      </label>
      <button type="submit">Submit</button>
    </form>

I then send it off to my lamdba function

  const response = await fetch("/.netlify/functions/sendmail", {
       method: "POST",
       body: JSON.stringify(formState),
     })

Now my state looks like the following in json after being sent to lamdbda function and being parsed

{ 
  name: 'Anders',
  package: 'silver',
  email: 'email@email.com',
  subject: 'fdsafa',
  weightLoss: 'on',
  strength: 'on',
  sport: 'on',
  message: 'fdsafasf'
} 

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.

const [formState, setFormState] = React.useState({
    name: "",
    package: `${data.datoCmsPricing.title}`,
    email: "",
    subject: "",
    weightLoss:"",
    strength:"",
    sport:"",
    message: "",
    data:{
      reasonArray:[
        {
          reason:""
        },
        {
          reason:""
        }
      ]
    }
  })

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

 const onChange = (e) => {
    if (e.target.type === 'checkbox'&& !e.target.checked) {
        setFormState({...formState, data:{ reasonArray:[ { reason:e.target.reason}, ]}});
    } 
    ...
 }

Form Changes

  ...
     <label>
        Weight Loss
        <input 
          type="checkbox"
          name="weightLoss"
          reason="weightLoss"
          checked={formState.weightLoss}
          onChange={onChange}
        />
        </label>
        <label>
        Strength 
        <input 
          type="checkbox"
          name="strength"
          reason="strength"
          checked={formState.strength}
          onChange={onChange}
        />
        </label>
        <label>
        Sport 
        <input 
          type="checkbox"
          name="sport"
          reason="sport"
          checked={formState.sport}
          onChange={onChange}
        />
        </label>
   ...

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.

{ 
   "name":"Anders",
   "package":"Silver",
   "email":"email@email.com",
   "subject":"fdsaf",
   "weightLoss":"on",
   "strength":"on",
   "sport":"on",
   "message":"fdsafas",
   "data":{ 
      "reasonArray":[ 
         { 
            "reason":""
         },
         { 
            "reason":""
         }
      ]
   }
}

Viewing all articles
Browse latest Browse all 138192

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>