0

我在使用 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]);
 };```
4

1 回答 1

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方法,因为它在找到某些东西时会短路(它会停在那里),然后修改该索引。

于 2020-07-10T04:48:37.770 回答