简体   繁体   English

更新 ReactJs 数组中的嵌套 object

[英]Update nested object in array in ReactJs

I am having trouble updating a nested object in an array in react state.我在反应 state 的数组中更新嵌套 object 时遇到问题。

I am trying to compare whether or not an item already exists in the state based off of the name of that item.我正在尝试根据该项目的名称比较 state 中是否已经存在该项目。

Here's what I am trying to have happen:这就是我想要发生的事情:

  1. Add item to cart.将商品添加到购物车。 If the product name is the same, then increase qty by one.如果产品名称相同,则将数量加一。 (this works) (这有效)

  2. If the name is not the same then add that new item to the state.如果名称不同,则将该新项目添加到 state。 (this also works) (这也有效)

  3. If I go back to a previous item that I have already added, and want to add it again, then I want to find that item in state, compare it to the current object that is being passed in, and update the quantity by one.如果我 go 回到我已经添加的上一个项目,并想再次添加它,那么我想在 state 中找到该项目,将其与当前的 ZA8CFDE6331BD59EB2AC96F8911C4B 进行比较,然后将其更新为 666。 (this doesn't work) (这不起作用)

I decided to implement the immutability-helper to simplify updating state.我决定实现 immutability -helper来简化更新 state。

I should note, that I am using NextJs and that this problem occurs only after I reload a new dynamic page.我应该注意,我正在使用 NextJs,并且仅在我重新加载新的动态页面后才会出现此问题。

Hope this is enough information... please let me know if more info is needed to be of assistance.希望这是足够的信息......如果需要更多信息来提供帮助,请告诉我。

Thanks in advance!提前致谢!

Update 2: This is another problem that I am running into... maybe the answer is obvious, but I thought I'd just put it out there to get a second set of eyes on it (if this should be a new question, please let me know).更新2:这是我遇到的另一个问题......也许答案很明显,但我想我只是把它放在那里让第二组眼睛关注它(如果这应该是一个新问题,请告诉我)。

I have some optional parameters that go along with each item.我有一些可选参数 go 以及每个项目。 The parameters are a nested object inside of the array.参数是数组内部的嵌套 object。 My solution was to use the following code to compare the data.我的解决方案是使用以下代码来比较数据。

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>;
}

However, I'm still getting the same sample output as shown below, regardless of what parameters I add to productParams.但是,无论我向 productParams 添加什么参数,我仍然得到相同的示例 output,如下所示。

Does anyone see anything wrong with my logic here?有人在这里看到我的逻辑有什么问题吗? I am at a loss of what to do...我不知道该怎么办...

UPDATE 1: I'm adding the object structure and sample output.更新 1:我正在添加 object 结构和示例 output。

Object structure: Object结构:

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

Sample Output From Chrome Dev Tools:来自 Chrome 开发工具的 Output 示例:

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>;
}

There is a small mistake in your code.您的代码中有一个小错误。 You should update cart outside of the map function instead of inside it when there are no matched object in the array.当阵列中没有匹配的 object 时,您应该在 map function 之外而不是在其中更新购物车。

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>;

}

What your code doing was this, if the current item(e) from cart array doesn't match with obj, it was adding that obj in the array.您的代码所做的是,如果购物车数组中的当前 item(e) 与 obj 不匹配,则会将该 obj 添加到数组中。 Which should be done only after you have iterate the array and confirmed that there are no data exist in the array which is same as obj.只有在迭代数组并确认数组中不存在与 obj 相同的数据后,才应执行该操作。

If that update doesn't solve your problem I might need some sample data(ie object structure, sample output etc...) from you to test this properly.如果该更新不能解决您的问题,我可能需要您提供一些示例数据(即 object 结构、示例 output 等......)来正确测试。

Please update your code with this one and it would be better if you can share obj data and cart data:请用这个更新您的代码,如果您可以共享 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]); } };

I solved it.我解决了。 InsomniacSabbir had the right idea. InsomniacSabbir 的想法是正确的。 I just had to modify the code a bit to get the result I wanted.我只需要稍微修改一下代码就可以得到我想要的结果。

Here's the solution这是解决方案

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>;
}

I had an if/else statement in map which was causing the problem.我在导致问题的 map 中有一个 if/else 语句。 I took out the else statement out of map and added another if statement into the function that checks if dataCheck is true/false.我从 map 中取出 else 语句,并在 function 中添加了另一个 if 语句,用于检查dataCheck是否为真/假。 dataCheck would be set to false only if the if statement in map was executed.仅当 map 中的 if 语句被执行时, dataCheck才会设置为 false。

Hope this answer helps!希望这个答案有帮助!

Thanks for the help everyone!感谢大家的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM