首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >React Js更改数组元素

React Js更改数组元素
EN

Stack Overflow用户
提问于 2021-10-03 06:48:56
回答 2查看 54关注 0票数 0

我在一个react js应用程序中有一个元素列表。

代码语言:javascript
运行
AI代码解释
复制
import "./styles.css";
import React from 'react';
const carsData = [
  {name: "first car", id: 1, meta: [{id:1, title:'first meta'}]},
  {name: "second car", id: 2, meta: [{id:2, title:'second meta'}]},
  {name: "third car", id: 3, meta: [{id:4, title:'last meta'}]},
]

export default function App({cars = carsData}) {
  const [carsState, setCarsState] = React.useState(cars) 
  const newItem = {name: "first car", id: 1, meta: [{id:10, title:'added meta'}]}
  

    const click = () => {
      setCarsState([...carsState, newItem])
    }
  return (
    <div className="App">
      <button onClick={click}>click</button>
      {
        carsState.map(c => {
          return <p key={c.name}>{c.name} - meta:
           {c.meta.map((m, k) => <span key={k}>{m.title}</span>)}</p>
        })
      }
    </div>
  );
}

如果用户单击该按钮,它应该更改数组中的第一项。现在,如果我单击该按钮,新的项目将添加到列表的末尾,但它应该会更改第一个项目,因为id是相同的。

为什么代码不能工作,如何更改以获得预期的结果?

演示:https://codesandbox.io/s/ecstatic-sound-rkgbe?file=/src/App.tsx:56-64

EN

回答 2

Stack Overflow用户

发布于 2021-10-03 07:00:10

问题出在下面这一行:

代码语言:javascript
运行
AI代码解释
复制
setCarsState([...carsState, newItem])

您必须过滤掉那些id不等于newItem.id的项,然后添加newItem,如下所示:

代码语言:javascript
运行
AI代码解释
复制
setCarsState([...carsState.filter(e => e.id !==newItem.id),newItem]);

代码语言:javascript
运行
AI代码解释
复制
import "./styles.css";
import React from "react";
const carsData = [
  { name: "first car", id: 1, meta: [{ id: 1, title: "first meta" }] },
  { name: "second car", id: 2, meta: [{ id: 2, title: "second meta" }] },
  { name: "third car", id: 3, meta: [{ id: 4, title: "last meta" }] }
];

export default function App({ cars = carsData }) {
  const [carsState, setCarsState] = React.useState(cars);
  const newItem = {
    name: "first car",
    id: 1,
    meta: [{ id: 10, title: "added meta" }]
  };

  const click = () => {
    setCarsState([...carsState.filter(e => e.id !==newItem.id),newItem]);
  };
  return (
    <div className="App">
      <button onClick={click}>click</button>
      {carsState.map((c) => {
        return (
          <p key={c.name}>
            {c.name} - meta:
            {c.meta.map((m, k) => (
              <span key={k}>{m.title}</span>
            ))}
          </p>
        );
      })}
    </div>
  );
}

这是sandbox

票数 1
EN

Stack Overflow用户

发布于 2021-10-03 07:12:08

好的,你的代码就像你说的那样-as push to the array。因为你并没有真正告诉它去做其他的事情。

如果您希望用新项替换旧项,如果它们具有相同的id值。我建议将初始array更改为object,其中每个valuekey是项的id。

我强烈建议你这样做,如果你想通过他们的id与你的项目进行交互,一旦你将你的操作扩展到包含很多项目,一个数组很快就会变得低效。

代码语言:javascript
运行
AI代码解释
复制
import React from 'react';

//notice we changed carsData from an array into an object. Notice 
//the keys are equal to each item's id
const carsData = {
  1:{name: "first car", id: 1, meta: [{id:1, title:'first meta'}]},
  2:{name: "second car", id: 2, meta: [{id:2, title:'second meta'}]},
  3:{name: "third car", id: 3, meta: [{id:4, title:'last meta'}]},
}

export default function App({cars = carsData}) {
  const [carsState, setCarsState] = React.useState(cars) 
  const newItem = {name: "first car", id: 1, meta: [{id:10, title:'added meta'}]}
  

    const click = () => {
      //We use the id of the new item as the key, 
      //this will enable us to replace the value of the old item because 
      //objects can't have the same key twice.
      setCarsState({...carsState, [newItem.id]: newItem})
      console.log(carsState)
    }
  return (
    <div className="App">
      <button onClick={click}>click</button>
      {
        //instead of mapping the array, now we map the
        //values of our object by using the method 
        //Object.values(carsState) which returns an array
        //of values from our object.
        Object.values(carsState).map(c => {
          return <p key={c.name}>{c.name} - meta:
           {c.meta.map((m, k) => <span key={k}>{m.title}</span>)}</p>
        })
      }
    </div>
  );
}

使用此解决方案将允许您按其id获取每一项。只需输入

代码语言:javascript
运行
AI代码解释
复制
carsData[id_of_item]

如果您的carsData是以来自DB的数组的形式出现的,那么您可以将其映射到一个对象中

代码语言:javascript
运行
AI代码解释
复制
var carsDataObject = {}
cars.map(item => carsDataObject[item.id] = item)
const [carsState, setCarsState] = React.useState(carsDataObject) 

然后,您可以使用carsDataObject而不是carsData数组

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69425965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文