更改嵌套在对象数组中的对象的状态

时间:2020-08-19 04:08:25

标签: javascript reactjs material-ui react-hooks

正如标题中所述,我试图更改嵌套在对象数组中的对象的状态。我只是无法使它正常工作。我已经在codesandbox中添加了我要尝试做的示例。

我正在使用Material-UI组件调用ToggleButton(链接至演示ToggleButton)。我想更改状态以切换组中的按钮。我能够将其用于创建功能,但无法将其用于更新功能。

尝试更改数组中对象的值对我来说不起作用。以下是我尝试未成功的一些事情。我想更改IsTrue:,以便可以切换按钮以显示用户选择。

        setAppetizer(true);            
        setRecipeObjectState({
            ...recipeObjectState,
            Category: [
                ...recipeObjectState.Category,
                {
                    IsTrue: appetizer,
                    category: "Appetizer",
                },
            ],
        });

这只会向我的按钮组添加更多按钮。

        setAppetizer(true);            
        setRecipeObjectState((prevState) => ({
            ...prevState,
            Category: [
                {
                    IsTrue: appetizer,
                    category: "Appetizer",
                },
            ],
        }));

我刚才丢在这一点上。我只想声明一下这是我的第一个React项目,不仅是学习框架的沙箱,而且我还是一名Jr。开发人员试图学习。我有搜索stackoverflow,没有任何帮助。我希望我提供了足够的信息,以帮助某人。

3 个答案:

答案 0 :(得分:1)

您的状态和应用似乎非常复杂,但是更新嵌套数组状态时的总体思路是在进行更新的每个级别上浅表复制该状态。使用array :: map将Category属性映射到新的数组对象引用,并在类别匹配时切换IsTrue“ selected”属性。

setRecipeObjectState((prevState) => ({
  ...prevState,
  Category: prevState.Category.map((category) =>
    category.category === newCategory // <-- newCategory value from toggled button
      ? {
          ...category,
          IsTrue: !category.IsTrue
        }
      : category
  )
}));

由于您的“选定”计算是selected={Boolean(item.IsTrue)},因此您需要确保IsTrue元素值实际上是 可切换的,也就是说,只需将布尔值存储在数组中即可

const recipeObject = {
  AuthorId: authorId,
  BookAuthor: bookAuthor,
  BookTitle: bookTitle,
  Calories: parseInt(calories),
  Category: [
    {
      IsTrue: false,
      category: "Appetizer"
    },
    {
      IsTrue: false,
      category: "Breakfast"
    },
    {
      IsTrue: false,
      category: "Soup / Salad"
    },
    {
      IsTrue: false,
      category: "Vegetarian"
    },
    {
      IsTrue: true,
      category: "Meat (Beef, Pork, Chicken)"
    },
    {
      IsTrue: false,
      category: "Fish"
    },
    {
      IsTrue: false,
      category: "Dessert"
    }
  ],
  Description: description,
  DurationInMinCook: parseInt(durationInMinCook),
  DurationInMinPrep: parseInt(durationInMinPrep),
  ImageUrl: imageUrl,
  Ingredients: addedIngredients, // array
  Instructions: addedInstructions, // array
  IsRecipe: true,
  Likes: 0,
  RecipeId: selectedRecipeId,
  ServingSize: parseInt(servingSize),
  Title: title,
  YouTubeUrl: youTubeUrl
};

Edit changing-state-of-object-nested-in-array-of-objects

答案 1 :(得分:0)

您更改了相同的引用,您需要呈现一个副本,否则该组件将无法呈现(浅比较):

尝试像这样更新状态。

const oldState = recipeObjectState;
oldState.Category = [
        {
          IsTrue: appetizer,
          category: "Appetizer"
        }
      ];

setRecipeObjectState(oldState);

答案 2 :(得分:0)

我没有尝试使用您的组件,因为它很大。

更新对象数组中的单个对象属性似乎是一个非常常见的用例。通常,这是您的操作方式。假设id是每个对象的唯一标识符,并且我们要切换selected

import React, { useState } from "react";
import "./styles.css";
import faker from "faker";

const array = [];
for (let id = 1; id < 10; id++) {
  array.push({
    id,
    name: faker.name.firstName(),
    age: faker.random.number(100),
    selected: false
  });
}

export default function App() {
  const [list, setList] = useState(array);

  const onClick = (id) => (event) => {
    setList((list) =>
      list.map((item) =>
        item.id === id ? { ...item, selected: !item.selected } : item
      )
    );
  };

  return (
    <div className="App">
      Click on a item:
      <ul>
        {list.map(({ id, name, age, selected }) => (
          <li key={id} onClick={onClick(id)} className="item">
            {name} {age}
            {selected ? " ✅" : null}
          </li>
        ))}
      </ul>
    </div>
  );
}

https://codesandbox.io/s/xenodochial-river-9sq6g?file=/src/App.js:0-825

相关问题