开发者问题收集

更改所提供 ID 的对象数组的值

2022-08-20
847

我如何更改所提供 ID 的值?我一直收到此 TypeError:无法设置未定义的属性(设置“select”)

const data = [
   {
    id: 1,
    select: false
   },
   {
    id: 2,
    select: true
   },
   {
   id: 3,
   select: true
   },
   {
   id: 4,
   select: false
   },
   {
   id: 5,
   select: false
   }
   ];
   const ids = [1, 2, 4];

   let d = [...data];
   for (let i = 0; i < d.length - 1; i++) {
   const objIndex: number = d?.findIndex((obj: any) => obj.id === ids[i]);
  d[objIndex].select = true;
  console.log(d);
  }

我想更改所提供 ID 的布尔值并创建一个新的数据对象(相同数据但更改了所提供 ID 的布尔值)需要帮助! 在此处输入图像描述

3个回答

也许不是在数据中搜索特定的 ID,而是在 ID 列表中搜索,这使其更简单,并且根据数据的大小和 ID 的数量,它可能会更快:

const data = [
   {
    id: 1,
    select: false
   },
   {
    id: 2,
    select: true
   },
   {
   id: 3,
   select: true
   },
   {
   id: 4,
   select: false
   },
   {
   id: 5,
   select: false
   }
   ];
   const ids = [1, 2, 4];

   for (let i = 0; i < data.length; i++) {

   if (ids.includes(data[i].id))
    data[i].select = true;
   
  }
  console.log(data);
Xyu
2022-08-20

您正在迭代 d 数组,并尝试使用未指向此数组中任何值的索引访问 ids 数组。因此 .findIndex 返回 -1 ,当您尝试在 d[objIndex] 中访问它时,它在那里也是未定义的,因为没有具有该索引的元素。

为了修复您的代码,您必须先迭代 ids 数组以获取具有精确 ID 的对象的索引,然后使用该索引更改值。

已修复代码:

const data = [
   {
    id: 1,
    select: false
   },
   {
    id: 2,
    select: true
   },
   {
   id: 3,
   select: true
   },
   {
   id: 4,
   select: false
   },
   {
   id: 5,
   select: false
   }
   ];
   const ids = [1, 2, 4];

   let d = [...data];
   ids.forEach((id) => {
       const objIndex: number = d?.findIndex((obj: any) => obj.id === id);

       // safe guard if there is no object with that id
       if (objIndex === -1) {
           return;
       }

       d[objIndex].select = true;
   })
Terminat
2022-08-20

您当前的 for 循环正在执行 d.length-1 次迭代,因此 i 将超出 ids 中索引的有效索引范围。因此,当您尝试对不是 ids 中索引的 i 值执行 ids[i] 时,您会返回 undefined ,这最终导致 .findIndex() 无法找到对象,因为没有具有 undefined id 属性的对象。这会导致下一行代码崩溃,因为它试图更新数组中不存在的对象。为了使您的代码正常工作,您的条件应该是 i < ids.length;

但是,假设 data 是一个状态值(我在这里收集了它,因为您将其标记为 并且您已经克隆了数据数组),您不应该像现在这样在 data 中修改对象。主要问题是 const d = [...data] 仅对数组进行浅表复制,因此对象仍然是引用,这意味着在执行 d[objIndex].select = true 时直接修改状态,这可能会导致重新渲染问题。

要解决这个问题,您可以对数组进行深度克隆,或者对数据使用 .map() 并返回一个新对象(如果需要更新),如下所示。下面的代码使用 spread 语法 ( ... ) 来创建一个具有当前对象所有属性的新对象(如果其 id ids 中),然后我们覆盖 select 的值以将其更新为 true

const data = [{ id: 1, select: false }, { id: 2, select: false }, { id: 3, select: false }, { id: 4, select: false }, { id: 5, select: false } ];
const ids = [1, 2, 4];

let newData = data.map(obj => ids.includes(obj.id) ? {...obj, select: true} : obj);
console.log(newData);
Nick Parsons
2022-08-20