Изменение объекта внутри массива с помощью useContext - PullRequest
0 голосов
/ 10 июля 2020

У меня возникли проблемы с использованием хука useContext в React. Я пытаюсь обновить состояние, полученное мной из контекста, но не могу понять, как это сделать. Мне удалось изменить значение свойства объекта, которое я хотел, но в итоге я добавляю еще один объект каждый раз, когда запускаю эту функцию. Это часть моего кода:

Метод внутри моего компонента «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 и при этом изменить одно значение свойства внутри объекта в таком массиве?

edit: Вот Компонент 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: Благодаря предложению Дизеля об использовании карты я придумал этот код, который делает свое дело!

   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 голосов
/ 10 июля 2020

Я предполагаю, что у вас есть доступ как к значению, так и к возможности установить состояние здесь:

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, поскольку он замыкается когда он что-то найдет (на этом он остановится), измените этот индекс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...