【问题标题】:what is the best way to setState which contains nested Object包含嵌套对象的 setState 的最佳方法是什么
【发布时间】:2021-10-23 19:29:52
【问题描述】:

我有一个包含多个字段的表单。
为了处理我使用受控组件的状态。
我使用的方法如下所示。
这最初可以工作,但随着需求的变化,我不得不使用嵌套对象来定义初始状态。
handleChange 不再正常工作。
我怎样才能为嵌套对象实现相同的结果。

  const [details, setDetails] = useState({
    description: null,
    platform: "Xbox",
    region: "ASIA",
    time:{
      start: "2017-05-24T10:30",
      end: "2017-05-28T10:30",
    },
    contact: {
      email: "",
      phone: "",
      twitter: "",
      discord: "",
    }
  });

  function handleChange(evt) {
    const value = evt.target.value;
    setDetails({
      ...details,
      [evt.target.name]: value,
    });
  }

示例组件

      <TextField
        label="Description"
        onChange={handleChange}
        name="description"
        value={details.description}    
      />
         <TextField
        label="email"
        onChange={handleChange}
        name="email"
        value={details.contact.email}    
      />

【问题讨论】:

    标签: reactjs use-state react-state-management


    【解决方案1】:

    我认为这样效果最好。

    function handleNestedChange(evt) {
      const value = evt.target.value;
      const keys = evt.target.name.split("."); 
      if(keys > 1){
        setDetails({
          ...details,
          [keys[0]]: {
            ...details[keys[0]],
            [keys[1]]: event.target.value
          }
        });
      }else{
         setDetails({
          ...details,
          [keys[0]]: event.target.value
          }
        });
      }
    }
    
    <TextField
            label="Email"
            onChange={handleChange}
            name="contact.email"
            value={details.description}    
          />
    

    如果您开始将大型嵌套对象存储到状态中,请查看包immutability-helper。它使仅更新对象中的特定字段变得更加容易,并且比重新创建整个事物要快得多。

    【讨论】:

      【解决方案2】:

      你可以像这样更新嵌套对象

      <TextField
              label="email"
              onChange={handleChange}
              name="contact_email"
              value={details.contact.email}    
            />
      
       function handleChange(evt) {
          const value = evt.target.value;
          const name = evt.target.name.split("_"); // [0: contact, 1: email]
           setDetails({ ...details, amount : { ...details[name[0]],  
          [name[1]]: value }})
        }
      

      【讨论】:

        【解决方案3】:

        懒惰的方式,但我会做这样的事情:

        function handleNestedChange(key, event) {
          setDetails({
            ...details,
            [key]: {
              ...details[key],
              [event.target.name]: event.target.value
            }
          });
        }
        
               <TextField
                label="email"
                onChange={(e) => handleNestedChange("contact", e)}
                name="email"
                value={details.contact.email}    
              />
        

        【讨论】:

          【解决方案4】:

          contact 中的文件需要其他 handleChange

            function handleChangeContact(evt) {
              const value = evt.target.value;
              setDetails({
                ...details,
                contact: {
                  ...details.contact,      
                  [evt.target.name]: value,
                }
              });
            }
          
           <TextField
              label="email"
              onChange={handleChangeContact}
              name="email"
              value={details.contact.email}    
            />
          

          【讨论】:

            猜你喜欢
            • 2023-03-27
            • 1970-01-01
            • 2020-08-10
            • 1970-01-01
            • 2012-12-29
            • 2022-01-25
            • 1970-01-01
            • 1970-01-01
            • 2010-10-12
            相关资源
            最近更新 更多