简体   繁体   English

如何在 React Hooks 中设置嵌套对象

[英]how to set a nested object in React Hooks

I'm working on a form which contains a section where users can choose the quantity and category of a concert ticket in a dropdown.我正在处理一个表单,其中包含一个部分,用户可以在其中从下拉列表中选择音乐会门票的数量和类别。 This component is dynamically created and it can have more items(quantity + category).这个组件是动态创建的,它可以有更多的项目(数量+类别)。 The dropdowns of the categories are related to each other.类别的下拉列表是相互关联的。 So if you choose one category the value of the other dropdowns should be set to the same selected value.因此,如果您选择一个类别,则其他下拉列表的值应设置为相同的选定值。 But I also need the name of each category dropdown for validation.但我还需要每个类别下拉列表的名称进行验证。

This is how I created the category object:这就是我创建类别对象的方式:

const createCategory = () => {
        let cat = {}
        let nestedCat = {}
        for (let it in item) {
            for (let bt in item[it].buyertypes) {
                cat2[item[it].buyertypes[bt].id] = ''
            }
            cat[item[it].id] = nestedCat
            nestedCat = {}
        }
        return cat
    } 
    const [category, setCategory] = useState(createCategory());

This is the initial object:这是初始对象:

{​
  9871: { 1: "", 2: "", 3: "" }
​
  9872: { 5: "", 6: "", 8: "" }
}

How I show and handle the ticket component我如何显示和处理工单组件

  const handleQuantity = e => {
      setQuantity({
          ...quantity,
          [e.target.name]: e.target.value
      });
  }

  const handleCategory = e => {
      setCategory({
          ...category,
          [e.target.name]: e.target.value
      });
 }

 const ShowData = () => {
        let ticketIem = []
        for (let it in item) {
            for (let bt in item[it].buyertypes) {
                let buyerType = item[it].buyertypes[bt]
                ticketIem.push({
                    'price': buyerType.prices, 'catId': item[it].id,
                    'qntId': item[it].buyertypes[bt].id
                })
            }
        }

        return (
            <div>
                {ticketIem.map((i, index) => (
                    <div key={index} >
                        <div>
                            <label>Number</label>
                            <select
                                value={quantity[i.qntId]}
                                onChange={handleQuantity}
                                name={i.qntId}
                            >
                                <option value={0}>0</option>
                                <option value={1}>1</option>
                            </select>
                        </div>
                        <div>
                            <label>Category</label>
                            <select
                                value={category[i.catId]}
                                onChange={handleCategory}
                                name={i.catId}
                            >
                                <option value="">Choose</option>
                                {categories.map((cat, index) => (
                                    <option key={index} value={cat.id} name={i.qntId}>
                                        {cat.description} {cat.value}
                                    </option>
                                ))}
                            </select>
                        </div>
                    </div>
                ))}
            </div>
        )
    }

After selecting an option in the dropdown the category object will be set like:在下拉列表中选择一个选项后,类别对象将设置为:

{
  9871: "11", 9872: "7"
}

but I expect:但我希望:

{​
  9871: { 1: "11", 2: "11", 3: "11" }
​
  9872: { 5: "7", 6: "7", 8: "7" }
}

If you want to set all the nested properties of a specific category or quantity then you'll need to also iterate the keys of those nested properties.如果要设置特定类别或数量的所有嵌套属性,则还需要迭代这些嵌套属性的键。 Use Object.keys to get an array of the nested object's keys, and reduce them into a new object with the new value set for each key.使用Object.keys获取嵌套对象键的数组,并将它们缩减为一个新对象,并为每个键设置新值。

I suggest also using a functional state update since each update depends on the existing/current state as it is shallowly copied into the next state.我建议还使用功能状态更新,因为每次更新都取决于现有/当前状态,因为它被浅复制到下一个状态。

const handleQuantity = (e) => {
  setQuantity((quantity) => ({
    ...quantity,
    [e.target.name]: Object.keys(quantity[e.target.name]).reduce(
      (obj, key) => ({
        ...obj,
        [key]: e.target.value
      }),
      {}
    )
  }));
};

const handleCategory = (e) => {
  setCategory((category) => ({
    ...category,
    [e.target.name]: Object.keys(category[e.target.name]).reduce(
      (obj, key) => ({
        ...obj,
        [key]: e.target.value
      }),
      {}
    )
  }));
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM