反应-更新状态数组

时间:2020-09-28 13:17:13

标签: javascript arrays reactjs object react-hooks

上下文

嗨,

我正在创建一个表单来创建虚拟机。信息跨多个页面(组件)收集,并集中在顶级组件中。

它的状态对象看起来像这样:

const [vmProp, setVmProp] = useState({
    name: "",
    image_id: "",
    image_name: "",
    volumesList: [],
    RAM: "",
    vcpu: "",
    autostart: true,
    });

问题

我希望能够向卷列表中添加/删除卷,并且我希望volumeList看起来像这样:

[
    {
      name: "main",
      size: 1024
    },
    {
      name: "backup",
      size: 2048
    },
    {
      name: "export",
      size: 2048
    }
]

我尝试过的事情

目前,我仅尝试添加卷。

1:可以工作,但不能产生我想要的东西

const handleAddVolume = (obj) => {
    setVmProp({ ...vmProp,
        volumesList: {
            ...vmProp.volumesList,
            [obj.name]: {
                size: obj.size,
            },
        } });
};

它正在工作,但是输出是:

[
    name: {
      size: 1024
    }
]

2:应该可以,但是不可以

const handleAddVolume = (obj) => {
    setVmProp({ ...vmProp,
        volumesList: {
            ...vmProp.volumesList,
            {
                name: obj.name,
                size: obj.size,
            },
        } });
};

输出:

[
    name: "main",
    size: 1024

]

您对如何处理此类状态对象有任何想法吗? 谢谢

4 个答案:

答案 0 :(得分:1)

如果您不需要从其他状态嵌套/取消嵌套卷列表,则将拥有更好的时间。 (更习惯的做法是为每个值都具有一个状态原子,但是对于简单的值(例如布尔值和字符串),这样做就可以。)

const [vmProps, setVmProps] = useState({
  name: "",
  image_id: "",
  image_name: "",
  RAM: "",
  vcpu: "",
  autostart: true,
});
const [volumesList, setVolumesList] = useState([]);

答案 1 :(得分:1)

volumesList 不应该是对象,而是将其作为 handleAddVolume 函数中的数组。

尝试以下方法,

const handleAddVolume = (obj) => {
    setVmProp({ ...vmProp,
        volumesList: [
            ...vmProp.volumesList,
            {
                name: obj.name,
                size: obj.size,
            }
        ] });
};

答案 2 :(得分:0)

这是一个可行的示例:

    Set OL = CreateObject("Outlook.Application")
    Set OLmail = OL.CreateItemFromTemplate("C:\Users\bhraman\Desktop\VBA practise\Add_picture_table_and_send_mail.msg")
    Set Rng = ThisWorkbook.Worksheets("Sheet2").Range("f7:k7")
    'Rng.Copy
    Rng.CopyPicture
    'Set p = ActiveSheet.Pictures.Paste
   ' p.Cut
    
    With OLmail
        .To = "bhraman@deloitte.com"
        .Subject = "Test"
    
        Set wordDoc = OLmail.GetInspector.WordEditor
        wordDoc.Range.Paste
        '.HTMLBody = Replace(OLmail.HTMLBody, "Trw", wordDoc.Range.Paste)
        '.display
        strbody = "Congratulations on your service anniversary with the team! We look forward to many more successful years with you!.<br><br>"
        '.HTMLBody = Replace(OLmail.HTMLBody, "TRW", wordDoc.Range.Paste)
        .HTMLBody = Replace(OLmail.HTMLBody, "Trw", strbody & "<br><br>" & p & "Regards,<br>Talent")
        '.HTMLBody = .HTMLBody & "<br><br>Best Regards,<br>Talent"
        .display

这只是概念的证明。基本上,const Example = (props) => { const inputRef = createRef(); const [vmProp, setVmProp] = useState({ name: "", image_id: "", image_name: "", volumesList: [], RAM: "", vcpu: "", autostart: true, }); const { volumesList } = vmProp; const handleAddVolume = (e) => { e.preventDefault(); const input = inputRef.current.value; setVmProp((prevVmProp) => { const newVmProp = { ...prevVmProp }; newVmProp.volumesList.push({ name: input, size: 1024, }); return newVmProp; }); // reset the input inputRef.current.value = ""; }; return ( <> <form> <input ref={inputRef} type="text" /> <button onClick={handleAddVolume}>Add volume</button> </form> {volumesList.map((volume) => ( <div key={volume.name}>{`${volume.name} - ${volume.size}`}</div> ))} </> ); }; export default Example; 接受一个函数,该函数获取最新状态值,因为更新是异步的,并返回状态的新值。因此,使用ES6's destructuring函数,我将复制名为setVmProp的{​​{1}}最新值,然后将一个新对象推入vmProp,然后返回{新添加的音量+其他所有内容。我从输入字段获得的newVmProp 的值。同样,这只是概念的证明。

答案 3 :(得分:0)

由于我需要能够添加/删除/替换数组中的对象,因此决定按如下所示创建其自己的状态:


const [volumesList, setVolumesList] = useState([]);

const handleAddVolume = (obj) => {
    setVolumesList((oldList) => [...oldList, obj]);
};

const handleRemoveVolume = (obj) => {
    setVolumesList((oldList) => oldList.filter((item) => item.name !== obj.name));
};

const handleEditVolume = (obj) => {
    setVolumesList(
        volumesList.map((volume) =>
            (volume.name === obj.name
                ? { ...volume, ...obj }
                : volume),
        ),
    );
};

感谢您的所有回答!