2

我在更新处于反应状态的数组中的嵌套对象时遇到问题。

我正在尝试根据该项目的名称比较该项目是否已经存在于该状态中。

这就是我想要发生的事情:

  1. 将商品添加到购物车。如果产品名称相同,则将数量加一。(这有效)

  2. 如果名称不同,则将该新项目添加到状态。(这也有效)

  3. 如果我回到我已经添加的上一个项目,并想再次添加它,那么我想找到该项目的状态,将其与正在传入的当前对象进行比较,并将数量更新一个。(这不起作用)

我决定实现immutability-helper来简化更新状态。

我应该注意,我正在使用 NextJs,并且仅在我重新加载新的动态页面后才会出现此问题。

希望这是足够的信息......如果需要更多信息来提供帮助,请告诉我。

提前致谢!

更新2: 这是我遇到的另一个问题......也许答案很明显,但我想我只是把它放在那里让第二组眼睛关注它(如果这应该是一个新问题,请告诉我)。

每个项目都有一些可选参数。参数是数组内的嵌套对象。我的解决方案是使用以下代码来比较数据。

import React, { createContext, useState, useEffect } from 'react';
import update from 'immutability-helper';
export const CartContext = createContext();

export function CartProvider(props) {
    const [ cart, setCart ] = useState([]);

//**********Start of the code to check the parameters of each item********

    const checkArr = (obj1, obj2) => {
        let newArr = [];
        function onlyInFirst(first, second) {
            for (let i = 0; i < first.length; i++) {
                if (second.indexOf(first[i]) === -1) {
                    newArr.push(first[i]);
                }
            }

        }

        onlyInFirst(obj1, obj2);
        onlyInFirst(obj2, obj1);

        if (newArr.length === 0) {
            return false;
        } else {
            return true;
        }
    };

//*******End of the code to check the parameters of each item**********

    const addItem = (obj) => {
        let dataCheck = true;
        if (cart.length != 0) {
            cart.map((e, i) => {
                if (e.productName === obj.productName) {
                    const prevVal = Object.values(e.productParams);
                    const currentVal = Object.values(obj.productParams);
                    dataCheck = checkArr(prevVal, currentVal);
                }
                if (dataCheck === false) {
                    const object = e;
                    const cartCopy = cart;
                    const newObj = update(object, { quantity: { $set: object.quantity + 1 } });
                    const newState = update(cartCopy, { [i]: { $set: newObj } });
                    setCart(newState);
                }
            });
        } else {
            setCart([ ...cart, obj ]);
        }
        if (dataCheck === true) {
            setCart([ ...cart, obj ]);
        }
    };

    return <CartContext.Provider value={{ cart, addItem }}>{props.children}</CartContext.Provider>;
}

但是,无论我向 productParams 添加了哪些参数,我仍然得到如下所示的相同示例输出。

有人在这里看到我的逻辑有什么问题吗?我不知道该怎么办...

更新 1:我正在添加对象结构和示例输出。

对象结构:

const obj = {
    productName: product.name, // product.name comes from api
    productParams: {}, // this is dynamically added elsewhere
    quantity: 1,
    productPrice: price 
}

Chrome 开发工具的示例输出:

3) [{…}, {…}, {…}]
0: {productName: "Item 1", productParams: {…}, quantity: 4, productPrice: 60}
1: {productName: "Item 2", productParams: {…}, quantity: 3, productPrice: 3000}
2: {productName: "Item 1", productParams: {…}, quantity: 3, productPrice: 60}
length: 3
__proto__: Array(0)
import React, { createContext, useState, useEffect } from 'react';
import update from 'immutability-helper';
export const CartContext = createContext();

export function CartProvider(props) {
    const [ cart, setCart ] = useState([]);

    const addItem = (obj) => {
        if (cart.length != 0) {
            cart.map((e, i) => {
                if (e.productName === obj.productName) {
                    const object = e;
                    const cartCopy = cart;
                    const newObj = update(object, { quantity: { $set: object.quantity + 1 } });
                    const newState = update(cartCopy, { [i]: { $set: newObj } });
                    setCart(newState);
                } else {
                    setCart([ ...cart, obj ]);
                }
            });
        } else {
            setCart([ ...cart, obj ]);
        }
    };

    return <CartContext.Provider value={{ cart, addItem }}>{props.children}</CartContext.Provider>;
}

4

3 回答 3

1

您的代码中有一个小错误。当数组中没有匹配的对象时,您应该在 map 函数之外而不是在其中更新购物车。

import React, { createContext, useState, useEffect } from 'react';
import update from 'immutability-helper';
export const CartContext = createContext();

export function CartProvider(props) {
    const [ cart, setCart ] = useState([]);

const addItem = (obj) => {
    if (cart.length != 0) {
        let dataExist = false;
        cart.map((e, i) => {
            if (e.productName === obj.productName) {
                const object = e;
                const cartCopy = cart;
                const newObj = update(object, { quantity: { $set: object.quantity + 1 } });
                const newState = update(cartCopy, { [i]: { $set: newObj } });
                setCart(newState);
                dataExist=true
            }
        });
        if(dataExist) {
            setCart([ ...cart, obj ]);
        }
    } else {
        setCart([ ...cart, obj ]);
    }
};

return <CartContext.Provider value={{ cart, addItem }}>{props.children}   </CartContext.Provider>;

}

您的代码所做的是,如果购物车数组中的当前 item(e) 与 obj 不匹配,则会将该 obj 添加到数组中。只有在您迭代数组并确认数组中不存在与 obj 相同的数据后,才应执行该操作。

如果该更新不能解决您的问题,我可能需要您提供一些示例数据(即对象结构、示例输出等...)来正确测试。

于 2019-11-15T09:36:14.420 回答
0

请用这个更新您的代码,如果您可以共享 obj 数据和购物车数据会更好:

const addItem = (obj) => {
    if (cart.length !== 0) {
      for (let i = 0; i <= cart.length; i += 1) {
        if (undefined !== cart[i]) {
          if (obj.productName === cart[i].productName) {
            const tempArr = [...cart];
            tempArr.quantity += 1;
            setCart(tempArr);
          } else {
            setCart([...cart, obj]);
          }
        }
      }
    } else {
      setCart([...cart, obj]);
    }
  };

于 2019-11-15T09:23:29.107 回答
0

我解决了!InsomniacSabbir 的想法是正确的。我只需要稍微修改一下代码就可以得到我想要的结果。

这是解决方案

import React, { createContext, useState, useEffect } from 'react';
import update from 'immutability-helper';
export const CartContext = createContext();

export function CartProvider(props) {
    const [ cart, setCart ] = useState([]);

    const addItem = (obj) => {
        let dataCheck = true;
        if (cart.length != 0) {
            cart.map((e, i) => {
                if (e.productName === obj.productName) {
                    const object = e;
                    const cartCopy = cart;
                    const newObj = update(object, { quantity: { $set: object.quantity + 1 } });
                    const newState = update(cartCopy, { [i]: { $set: newObj } });
                    setCart(newState);
                    dataCheck = false;
                }
            });
        } else {
            setCart([ ...cart, obj ]);
        }
        if (dataCheck === true) {
            setCart([ ...cart, obj ]);
        }
    };

    return <CartContext.Provider value={{ cart, addItem }}>{props.children}</CartContext.Provider>;
}

我在地图中有一个 if/else 语句导致了问题。我从 map 中取出 else 语句,并将另一个 if 语句添加到检查dataCheck是否为真/假的函数中。只有当 map 中的 if 语句被执行时, dataCheck才会被设置为 false。

希望这个答案有帮助!

感谢大家的帮助!

于 2019-11-15T13:50:19.010 回答