用react更新状态下的对象数组

时间:2020-05-24 22:05:12

标签: javascript reactjs

我正试图使购物车产生反应,并希望每次点击都能增加商品的数量。我可以找到的所有示例都只是将一个新项目推送到数组,而不是增加现有项目的数量,结果是:

[
{id: 1, item: pants, qty: 1},
{id: 1, item: pants, qty: 1},
{id: 2, item: shirt, qty: 1}
]

当我的目标是:

[
{id: 1, item: pants, qty: 2},
{id: 2, item: shirt, qty: 1}
]

我提出了以下可行的方法,但它非常难看。我在寻找更优雅的东西。

    function App() {

      const [items, setItems] = useState([]);

      const updateState = (item) => (e) => {
        let newArray = [...items];

        if (items.some((el) => el.id === item.id)) {
          const place = items.findIndex((obj) => obj.id === item.id);
          newArray[place] = {
            id: item.id,
            item: item.name,
            qty: items[place].qty + 1,
          };
        } else {
          newArray.push({ id: item.id, item: item.name, qty: 1 });
        }

        console.log(newArray);
        setItems(newArray);
     };

     return (
       <div>
         <button onClick={updateState({ id: 1, name: 'pants' })}></button>
         <button onClick={updateState({ id: 2, name: 'shirt' })}></button>
       </div>
     );
   }

这是有效的丑陋版本的代码沙箱。 https://codesandbox.io/s/billowing-resonance-f1ip6?file=/src/App.js

3 个答案:

答案 0 :(得分:0)

您做对了。最终会有一些库可以帮助您使代码更漂亮,例如DotProp,但它只会处理您在后台所做的事情。

最终,您可以通过直接获取indexOf并检查if语句中是否未定义indexOf来避免执行.some(...)

答案 1 :(得分:0)

您的实现很好,但是为了保持整洁,我认为您应该创建一个新函数,该函数接受数组和项目,如果尚不存在则插入该项目,或者如果该项目存在则更新项目的数量在数组中。

这是另一种实现方式。

const arr = [
{id: 1, item: "pants", qty: 1},
{id: 2, item: "shirt", qty: 1}
]


const addItem = (arr, item) => {
  const idx = arr.findIndex(el => el.id === item.id);

  if (idx === -1) {
    return [...arr, item]
  }

  arr[idx] = {...arr[idx], qty: arr[idx].qty + 1}
  return [...arr];
}

let newArr = addItem(arr, {id: 1, item: "pants", qty: 1})
newArr = addItem(newArr, {id: 3, item: "jeans", qty: 1})
console.log(newArr)

答案 2 :(得分:0)

我认为这并不难看。你可以尝试吗?

import React from "react"
import "./styles.css"

export default function App() {
  const [items, setItems] = React.useState([
    {id: 1, name: 'pants'},
    {id: 2, name: 'shirt'}
  ])

  const handleClick = (i) => {
    setItems(items.map((item, curIndex) =>
           i === curIndex ? { ...item, qty: ++item.qty||1 } : item
    ))
  }

  return (
   <div>
     {items.map((item,index)=>(
       <button onClick={()=>handleClick(index)}>{item.qty || 0}</button>
     ))}
   </div>
 )
}