как установить вложенный объект в React Hooks

#javascript #json #reactjs #react-hooks

#javascript #json #reactjs #реагирующие крючки

Вопрос:

Я работаю над формой, которая содержит раздел, в котором пользователи могут выбирать количество и категорию билета на концерт в выпадающем списке. Этот компонент создается динамически и может содержать больше элементов (количество категория). Выпадающие списки категорий связаны друг с другом. Поэтому, если вы выбираете одну категорию, значение других выпадающих списков должно быть установлено на то же выбранное значение. Но мне также нужно имя выпадающего списка каждой категории для проверки.

Вот как я создал объект категории:

 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());
  

Это начальный объект:

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

Как я показываю и обрабатываю компонент ticket

   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>
        )
    }
  

После выбора опции в выпадающем списке объект категории будет установлен как:

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

но я ожидаю:

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

Ответ №1:

Если вы хотите установить все вложенные свойства определенной категории или количества, вам также потребуется выполнить итерацию ключей этих вложенных свойств. Используется Object.keys для получения массива ключей вложенного объекта и преобразования их в новый объект с новым значением, установленным для каждого ключа.

Я предлагаю также использовать обновление функционального состояния, поскольку каждое обновление зависит от существующего / текущего состояния, поскольку оно неглубоко копируется в следующее состояние.

 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
      }),
      {}
    )
  }));
};
  

Комментарии:

1. Это работает отлично @DrewReese. Что, если я хочу установить для каждого вложенного свойства то, что пользователь выбирает в раскрывающемся списке?

2. @NimaPostanchi Разве это не то, что target.value значение? Или я не понимаю ваш последующий вопрос?

3. @DrewResse в предыдущем случае я хотел присвоить всем вложенным свойствам определенной категории определенное значение, чтобы все выпадающие списки имели одинаковое значение, а предложенный вами код работал идеально. Теперь я хочу установить значение каждого выпадающего списка на то, что выбирает пользователь (не одинаковое значение для всех выпадающих списков). Теперь я хочу, чтобы объект выглядел как {​ 9871: { 1: "4", 2: "3", 3: "1" } ​ 9872: { 5: "1", 6: "7", 8: "4" } } target.value дает правильное значение, но я не могу установить для него правильное вложенное свойство. Надеюсь, я прояснил. Заранее спасибо за вашу помощь.

4. @NimaPostanchi Я думаю, мне нужно немного больше контекста, так как сейчас я не вижу, какой пользовательский интерфейс относится к вложенным значениям. Он выглядит как name={i.qntId} и name={i.catId} является ключами внешнего количества / категории ( event.target.name ), а выбранным параметром является значение ( event.target.value ), поэтому я не уверен, что вы используете для промежуточных ключей. Не могли бы вы предоставить работающий codesandbox, который я мог бы проверить?

5. @DrewResse на самом деле этот вариант использования является расширением для предыдущего случая. Каждый раз, когда пользователь выбирает количество количества, будут показаны некоторые поля ввода для промо-кода на основе выбранного числа. Я создаю элементы этого промокода во вложенном объекте в обработчике события количества и присваиваю им имя ключа. Я не могу передать правильное имя ={} . здесь выполняется codesandbox , я хочу установить для объекта promotionCode каждого поля promotion значение e.taget.value в handleCode.