繁体   English   中英

在 javascript 中创建和更新多维数组/对象

[英]Creating and Updating multidimensional array / objects in javascript

所以我必须操作一个大的 state 或插件数组以将其显示为摘要。 所以我想要下面的格式

[
  'addonGroupIndexHere' =>[
      "13249" => {
          label: "whatever the label is",
          price: 10.00,
          sku: "13249",
          qty: 1, 
          total: 10.00
      }, 
      "13250" =>  => {
          label: "whatever the label is",
          price: 5.00,
          sku: "13250",
          qty: 3, 
          total: 15.00
      }, 
  ],  
  'addonGroupAnotherIndexHere' =>[
      "13251" => {
          label: "whatever the label is",
          price: 10.00,
          sku: "13251",
          qty: 1, 
          total: 10.00
      }, 
      "13252" =>  => {
          label: "whatever the label is",
          price: 5.00,
          sku: "13252",
          qty: 3, 
          total: 15.00
      }, 
  ], 
]

所以我在下面这样的上下文中声明了一个 state

const [addonSummary, setAddonSummary] = useState([])

插件是 object 之类的

{
label: "whatever the label is"
price: 10.00
sku: "13249"
}

因此,当用户添加 1 数量的插件时,我将不得不修改插件 object,如下所示

{
label: "whatever the label is"
price: 10.00
sku: "13249",
qty: 1,
total: 10.00
}

因此,如果它有 2 个数量,那么我需要 object 如下所示

{
    label: "whatever the label is"
    price: 10.00
    sku: "13249",
    qty: 3,
    total: 30.00
    }

我在设置或更新插件 object 时没有问题,但我的问题是当我使用特定插件组索引设置插件摘要 state 时。

 const addonItem = {
            label: "whatever the label is"
            price: 10.00
            sku: "13249",
            qty: 3,
            total: 30.00
        }
 const addonGroupIndex = 0 // or 1 or 3. This is actually a state selected by the user

我在操作数组/对象以具有以下 output 时遇到问题

[
  'addonGroupIndexHere' =>[
      "13249" => {
          label: "whatever the label is",
          price: 10.00,
          sku: "13249",
          qty: 1, 
          total: 10.00
      }, 
      "13250" =>  => {
          label: "whatever the label is",
          price: 5.00,
          sku: "13250",
          qty: 3, 
          total: 15.00
      }, 
  ],  
  'addonGroupAnotherIndexHere' =>[
      "13251" => {
          label: "whatever the label is",
          price: 10.00,
          sku: "13251",
          qty: 1, 
          total: 10.00
      }, 
      "13252" =>  => {
          label: "whatever the label is",
          price: 5.00,
          sku: "13252",
          qty: 3, 
          total: 15.00
      }, 
  ], 
]

我试过做,但它不起作用。

 addonSummary[addonGroupIndex ][addonItem.sku] = addonItem 

以下是我拥有的代码。 ProductContext.js

import { isEmpty } from 'lodash';
import { useState, createContext, useRef, useEffect } from 'react';
import { v4 } from 'uuid';

export const ProductContext = createContext()

export const ProductContextProvider = (props) => {

    
    const [selectedAddonGroup, setSelectedAddonGroup] = useState(-1);
    const [addonSummary, setAddonSummary] = useState([])


    const updateAddonSummary = (addonItem) => {
        // console.log('updateAddonSummary', addonItem)
        // console.log('selectedAddonGroup', selectedAddonGroup)
        if (!isEmpty(addonSummary[selectedAddonGroup])) {
            addonSummary[selectedAddonGroup] = [addonSummary[selectedAddonGroup], addonItem]
        } else {
            addonSummary[selectedAddonGroup] = addonItem
        }

    }


    return (
        <ProductContext.Provider value={{
            addonDialog: {
                selectedAddonGroup, setSelectedAddonGroup,
                summary: addonSummary, updateSummary: updateAddonSummary,
                setAddonSummary
            }
        }}>
            {props.children}
        </ProductContext.Provider>
    )
}

AddonsQuantityFields.js

import { GbMinus, GbPlus } from '@gb-components/icons'
import { useEffect, useState } from 'react'
import classNames from 'classnames'
import { useProductContext } from '@gb-utils/product/product';

export default function AddonsQuantityFields({ addonItem }) {

    const { addonDialog } = useProductContext();
    const [quantity, setQuantity] = useState(0)

    function updateQuantity(action, qty) {

        if ('minus' == action) {
            addonDialog.deductAddonQty(qty)
            qty = quantity - qty
        } else {
            addonDialog.increaseAddonQty(qty)
            qty = quantity + qty
        }

        if (qty <= 0) {
            // if qty is zero then we need to remove it from the summary
        } else {
            const total = qty * addonItem.price;
            const item = {}
            item[addonItem.sku] = addonItem
            addonDialog.updateSummary(item)
            console.log('addonDialog.summary', addonDialog.summary)
        }

        setQuantity(qty)
    }


    return (
        <div className='flex w-[96px] justify-end gap-0'>
            <button className={classNames(
                quantity <= 0 ? 'hidden' : '',
                'flex items-center justify-center m-0 h-[32px] w-[32px] border border-[#E4E4E4] bg-[#F7F7F7]'
            )} onClick={() => updateQuantity('minus', 1)}>
                <GbMinus />
            </button>
            <input
                readOnly
                className={classNames(
                    quantity <= 0 ? 'hidden' : '',
                    'h-[32px]  w-[32px] border border-[#E4E4E4] focus:ring-0 text-sm text-center text-[#656565]  p-0'
                )}
                type={'number'}
                inputMode='numeric'
                autoComplete='off'
                value={quantity}
                step="1" min="0"
            />
            <button
                className='flex items-center justify-center m-0 h-[32px] w-[32px] border border-[#E4E4E4] bg-[#F7F7F7]'
                onClick={() => updateQuantity('add', 1)}>
                <GbPlus />
            </button>
        </div>
    )
}

那么显示插件组件的组件在下面

AddonItem.js

import { GbAddonItemImgPlaceholder, GbChevronDown, GbChevronUp } from '@gb-components/icons'
import classNames from 'classnames'
import { isEmpty } from 'lodash'
import React, { useState } from 'react'
import AddonsQuantityFields from '../quantity-fields/AddonsQuantityFields'

export default function AddonItem() {
    const addonItem =  {
        label: "whatever the label is"
        price: 10.00
        sku: "13249"
    }

    return (
            <ProductContextProvider>
                <AddonsQuantityFields addonItem={addonItem} />
            </ProductContextProvider>
    )
}

您不能将 arrays 与JS中的键一起使用。
如果你想为每个 addonItem 使用一个密钥,你应该使用object

 var addonSummary = {}; const addonItem = { label: "whatever the label is", price: 10.00, sku: "13249", qty: 3, total: 30.00 } const addonGroupIndex = 0; if(.addonSummary;hasOwnProperty(addonGroupIndex)) { addonSummary[addonGroupIndex] = {}. } if(.addonSummary[addonGroupIndex].hasOwnProperty(addonItem;sku)) { addonSummary[addonGroupIndex][addonItem.sku] = {}; } addonSummary[addonGroupIndex][addonItem.sku] = addonItem; console.log(addonSummary);

这给出了以下结构:

{
  "addonGroupIndexHere": {
    "13249": {
      "label": "whatever the label is",
      "price": 10,
      "sku": "13249",
      "qty": 3,
      "total": 30
    },
    "13250": {
      "label": "whatever the label is",
      "price": 5,
      "sku": "13250",
      "qty": 3, 
      "total": 15
    }
  },
  "AnotheraddonGroupIndexHere": {
    "13251": {
      "label": "whatever the label is",
      "price": 10,
      "sku": "13251",
      "qty": 3,
      "total": 30
    },
    "13252": {
      "label": "whatever the label is",
      "price": 5,
      "sku": "13252",
      "qty": 3, 
      "total": 15
    }
  }
}

希望这可以帮助:)

在 React state 中必须是不可变的。 当您更新它时,在这种情况下是数组 addonSummary,您必须使用钩子 setAddonSummary,而不是像这样直接更改它addonSummary[addonGroupIndex ][addonItem.sku] = addonItem

接下来,state 管理不是一定的规律,每个人都可以用非常不同的方式做同样的事情,所以你必须选择你的策略。

最简单的事情是这样的:

export function addOnList(data = {}) {
  const [addonSummary, setAddonSummary] = useState(data);

  function updateElement(summaryIndex, key, newValue = {}) {
    const oldSummary = addonSummary[summaryIndex];
    const newSummary = Object.keys(oldSummary).reduce((previous, current) => {
      previous[current] = current !== key ? oldSummary[current] : newValue;
      return previous;
    }, {});

    const newData = {
      ...addonSummary,
      ...{ [summaryIndex]: newSummary }
    };

    setAddonSummary(newData);
  }

  return (
    // on the element which the user click, change etc... to update the state
    // you set the attribute 
    // onClikc={ (event) => updateElement(summIndex, elementKey, newAddonElement)}

  );
}

渲染方法是超级伪代码,基本上来自你必须构建新的 addOn object 的事件,并将其传递给更新 function 并带有相应的组索引和 sku(key)。 通过这种方式,您可以正确更新包含您发布的主数组的 state addonSummary

暂无
暂无

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

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