Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用状态钩子。单击复选框时,如何使用数组更新json对象的状态_Javascript_Json_Reactjs_Handlebars.js_React Hooks - Fatal编程技术网

Javascript 使用状态钩子。单击复选框时,如何使用数组更新json对象的状态

Javascript 使用状态钩子。单击复选框时,如何使用数组更新json对象的状态,javascript,json,reactjs,handlebars.js,react-hooks,Javascript,Json,Reactjs,Handlebars.js,React Hooks,我通过lamda服务器将状态作为字符串化变量从表单发送到POST请求,然后lamda服务器解析状态并将状态发送到sendgrid,我在那里使用send grids模板功能。这要求我将json格式化为这样,以便循环一个特定部分(多个复选框),所有这些部分都应该具有相同的键,但具有不同的值,由表单中的reason=“Weight Loss”设置。下面是最终json的形成方式 { "name" :"anders", "message" : "winfsdafasfdsfsadfsadnipeg

我通过lamda服务器将状态作为字符串化变量从表单发送到POST请求,然后lamda服务器解析状态并将状态发送到sendgrid,我在那里使用send grids模板功能。这要求我将json格式化为这样,以便循环一个特定部分(多个复选框),所有这些部分都应该具有相同的键,但具有不同的值,由表单中的
reason=“Weight Loss”
设置。下面是最终json的形成方式

{
  "name" :"anders",
  "message" : "winfsdafasfdsfsadfsadnipeg",
  "package" : "silver",
  "email" : "email@email.com",
  "subject" : "fdsafas",
  "data":{
      "reasonArray":[
         {
            "reason":"weightLoss"
         },
         {
            "reason":"Sport"
         }
      ]
   }
}
然后,我可以做一些魔术和循环的原因,被选中的复选框

<ol>
  {{#each data.reasonArray}}
    <li>{{this.reason}} </li>
  {{/each}}
</ol>
然后,我有了下面的
onChange
事件,该事件将状态设置为输入字段的名称作为键,值或选中状态作为值。看到这里了吗

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 });
    }
 }
这是我的表格

<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>
现在,在发送到lamdbda函数并进行解析后,我的状态在json中看起来如下

{ 
  name: 'Anders',
  package: 'silver',
  email: 'email@email.com',
  subject: 'fdsafa',
  weightLoss: 'on',
  strength: 'on',
  sport: 'on',
  message: 'fdsafasf'
} 
现在我想让我的初始状态看起来像sendgird想要的格式,所以这就是我尝试的状态设置

const [formState, setFormState] = React.useState({
    name: "",
    package: `${data.datoCmsPricing.title}`,
    email: "",
    subject: "",
    weightLoss:"",
    strength:"",
    sport:"",
    message: "",
    data:{
      reasonArray:[
        {
          reason:""
        },
        {
          reason:""
        }
      ]
    }
  })
然后,我尝试用以下内容更新onChange事件的检查值,我还更新了我的表单,因此它会获取一个用户友好的名称。请参见下面的代码

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

  ...
     <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>
   ...
拉比的回答

  ...

 const prepareDataForApi = (formData) => {
  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 => {
    if(newFormData.reasons[key]){
      newFormData.data.reasonArray.push({reason: key})
    }
  });

  delete newFormData.reasons;

  return newFormData;
}



 const submitForm = async (e) => {
  e.preventDefault();

  setForm(false);



  // const newFormData = prepareDataForApi(formData); 
     const newFormData = prepareDataForApi(formState);

  console.log(newFormData);

...

更新密钥时,新的
onChange
似乎没有替换所有嵌套值。请尝试以下方法:

setFormState({
…formState,
数据:{
…formState.data,//保留来自上一个数据对象的键(如果它只包含您正在指定的键,则不需要)
reasonArray:[
…formState.data.reasonArray,//保留来自reasonArray的以前条目
{原因:e.target.reason},
]
}
});
另一种方法是使用
效果

const[formState,setFormState]=React.useState({…}):
//每次减肥改变时都会跑步
React.useffect(()=>{
让newReasonArray
if(formState.失重){
newReasonArray=[…formState.reasonArray];//所以我们不改变状态
push({reason:'weightLoss'});
}否则{
//如果要将其从阵列中移除,请取消选中它
newReasonArray=[…formState.reasonArray];
newReasonArray.filter((reason)=>(reason.reason!=“失重”);
}
console.log(newReasonArray)//测试其更新是否正确
//设置新数组的状态
setFormState({…formState,数据:{reasonArray:newReasonArray}});
},[formState.失重];

1.保持初始状态如下:

{ 
   "name":"Anders",
   "package":"Silver",
   "email":"email@email.com",
   "subject":"fdsaf",
   "message":"fdsafas",
   "reasons": {
      "weightLoss": true,
      "strength": true,
      "sport": true,
   }
}
  • 修改onChange():
  • 更改表单的
    onSubmit()
    : 在调用api之前,调用converter函数,该函数将
    formState
    转换为lambda函数所需的JSON格式

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

  • 嗯,我得到了一个
    \uuuu proto\uuu:Object
    ,其中
    数据{Reason…
    应该去。我得到的是一个reasonArray没有定义,我一定是在某个地方搞砸了。嗯,我的
    Reason
    的值仍然是空的。你是在尝试添加到原因数组中?还是尝试修改当前值?我想两者都做。我想我必须让数组处于启动状态。但是如果我可以在后面添加数组,并更改
    reason
    的值,这将是理想的。如果这有意义,我希望reason更改为
    Weight Loss
    Sport
    的值,这一切取决于复选框中选中的内容。但它需要中间的空格(取决于)因此,它在结尾的电子邮件中更具可读性。我是将prepareDataForApi函数放在表单提交处理程序的外部还是内部?然后我将console.log(newFormData)用于测试?将其放在提交处理程序的外部,只需调用
    prepareDataForApi
    内部提交处理程序,类似这样:`prepareDataForApi=()=>{func def…}onSubmit=()=>{const newFromData=prepareDataForApi(formData);console.log(newFromData);}`do I控制台日志
    newFormData
    内部如下
    prepareDataForApi=()=>{console.log(newFormData);}
    ?如果您想在浏览器控制台中打印newFromData,可以这样做。是的,我只想在进入下一步之前先调试一下。我会试试的
      ...
    
     const prepareDataForApi = (formData) => {
      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 => {
        if(newFormData.reasons[key]){
          newFormData.data.reasonArray.push({reason: key})
        }
      });
    
      delete newFormData.reasons;
    
      return newFormData;
    }
    
    
    
     const submitForm = async (e) => {
      e.preventDefault();
    
      setForm(false);
    
    
    
      // const newFormData = prepareDataForApi(formData); 
         const newFormData = prepareDataForApi(formState);
    
      console.log(newFormData);
    
    ...
    
    { 
       "name":"Anders",
       "package":"Silver",
       "email":"email@email.com",
       "subject":"fdsaf",
       "message":"fdsafas",
       "reasons": {
          "weightLoss": true,
          "strength": true,
          "sport": true,
       }
    }
    
     const onChange = (e) => {
        if (e.target.type === 'checkbox') {
            const changedReason = e.target.getAttribute('name');
            setFormState({...formState, reasons:{...formState.reasons, [changedReason]: !formState.reasons[changedReason]}});
        } 
        ...
     }
    
    
    const prepareDataForApi = (formData) => {
      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 => {
        if(newFormData.reasons[key]){
          newFormData.data.reasonArray.push({reason: key})
        }
      });
    
      delete newFormData.reasons;
    
      return newFormData;
    }