使用useContext修改数组内的对象

时间:2020-07-10 03:26:59

标签: reactjs react-hooks use-context

我在使用React的useContext钩子时遇到了麻烦。我正在尝试更新从上下文中获得的状态,但是我不知道如何操作。我设法更改了想要的对象的属性值,但每次运行此函数时最终都会添加另一个对象。这是我的一些代码:

“ CartItem”组件中的方法。

const addToQuantity = () => {
    cartValue.forEach((item) => {
      let boolean = Object.values(item).includes(props.name);
      console.log(boolean);
      if (boolean) {
        setCartValue((currentState) => [...currentState, item.quantity++])
      } else {
        return null;
      }
    });
  };

呈现“ CartItem”的“购物车组件”

  const { cart, catalogue } = useContext(ShoppingContext);
  const [catalogueValue] = catalogue;
  const [cartValue, setCartValue] = cart;

  const quantiFyCartItems = () => {
    let arr = catalogueValue.map((item) => item.name);
    let resultArr = [];
    arr.forEach((item) => {
      resultArr.push(
        cartValue.filter((element) => item === element.name).length
      );
    });
    return resultArr;
  };

  return (
    <div>
      {cartValue.map((item, idx) => (
        <div key={idx}>
          <CartItem
            name={item.name}
            price={item.price}
            quantity={item.quantity}
            id={item.id}
          />
          <button onClick={quantiFyCartItems}>test</button>
        </div>
      ))}
    </div>
  );
};

那么我如何保留我的cartValue数组中的先前对象,并且仍然在此类数组中的对象内部修改单个属性值?

编辑:这是ShoppingContext组件!

import React, { useState, createContext, useEffect } from "react";
import axios from "axios";

export const ShoppingContext = createContext();

const PRODUCTS_ENDPOINT =
  "https://shielded-wildwood-82973.herokuapp.com/products.json";

const VOUCHER_ENDPOINT =
  "https://shielded-wildwood-82973.herokuapp.com/vouchers.json";

export const ShoppingProvider = (props) => {
  const [catalogue, setCatalogue] = useState([]);
  const [cart, setCart] = useState([]);
  const [vouchers, setVouchers] = useState([]);

  useEffect(() => {
    getCatalogueFromApi();
    getVoucherFromApi();
  }, []);

  const getCatalogueFromApi = () => {
    axios
      .get(PRODUCTS_ENDPOINT)
      .then((response) => setCatalogue(response.data.products))
      .catch((error) => console.log(error));
  };

  const getVoucherFromApi = () => {
    axios
      .get(VOUCHER_ENDPOINT)
      .then((response) => setVouchers(response.data.vouchers))
      .catch((error) => console.log(error));
  };

  return (
    <ShoppingContext.Provider
      value={{
        catalogue: [catalogue, setCatalogue],
        cart: [cart, setCart],
        vouchers: [vouchers, setVouchers],
      }}
    >
      {props.children}
    </ShoppingContext.Provider>
  );
};

edit2:由于Diesel建议使用地图,我想出了实现此目的的代码!

   const newCartValue = cartValue.map((item) => {
     const boolean = Object.values(item).includes(props.name);
     if (boolean && item.quantity < item.available) {
       item.quantity++;
     }
     return item;
   });
   removeFromStock();
   setCartValue(() => [...newCartValue]);
 };```

1 个答案:

答案 0 :(得分:0)

我假设您可以同时访问值和设置状态的能力:

const addToQuantity = () => {
    cartValue.forEach((item) => {
      let boolean = Object.values(item).includes(props.name);
      console.log(boolean);
      if (boolean) {
        setCartValue((currentState) => [...currentState, item.quantity++])
      } else {
        return null;
      }
    });
  };

现在...如果您执行[...currentState, item.quantity++],则将始终添加一个新项目。你什么都没改变。您还在每个项目上运行setCartValue,这不是必需的。我不确定有多少可以更改,但是您似乎想更改值。这就是map的优点。

const addToQuantity = () => {
    setCartValue((previousCartValue) => {
      const newCartValue = previousCartValue.map((item) => {
        const boolean = Object.values(item).includes(props.name);
        console.log(boolean);
        if (boolean) {
          return item.quantity++;
        } else {
          return null;
        }
      });
      return newCartValue;
    });
  };

您获取所有值,进行所需的修改,然后可以将其设置为新状态。另外,它还创建了一个新数组,这很不错,因为它不会使您的数据发生变异。

此外,如果您知道只有一项会符合您的条件,请考虑使用.findIndex方法,因为该方法在发现某物时会短路(它将在那里停止),然后修改该索引。