reactjs useState更新对象数组内的特定对象

时间:2020-02-22 23:41:32

标签: reactjs

我正在从事杂货清单项目。对于这个项目,当用户输入一个项目时,我希望能够编辑该项目。我将所有内容存储在处于状态的对象数组中。我的对象的结构是:

{
 product: 'toast',
 category: 'bakery',
 quantity: 3,
 type: 'each
},
{
 product: 'apple',
 category: 'produce',
 quantity: 2,
 type: 'each'
},
{
 product: 'hamburger',
 category: 'meat',
 quantity: 1,
 type: 'Lb'
}

我想做的是让用户在卡类型功能内选择这些对象之一,然后对其进行更新。目前,我可以将项目添加到列表中,但不能更新它们。

我尝试了setList(list[i].txt=v)setList(list=>list[i].product=v)以及其他尝试针对特定对象的变体。任何想法将不胜感激。

以下是我的主要app.js代码。注意:const Change()是我尝试更新对象的地方。我要传递的变量来自我的item.js代码

import React ,{useState,useEffect} from 'react';
import List from './components/list';
import Header from './components/header';

function App() {
  const [list, setList] = useState([]);
  const Add = (p, c, q, t, crt) => {
    console.log({product: p, category: c, quantity: q, type: t, cart: crt})
    setList(list=>[...list,{product:p, category:c, quantity:q, type:t, cart: crt}])
  }
  const Change = (i, txt, v) => {
    //setList(list[i].txt=v)
    console.log('id: ' + i + ' topic: ' + txt + ' value: ' +v)
    setList(list=>list[i].product=v)
  }
  const Delete = () => {

  }
  return (
    <div>
      {console.log(list)}
      <h1>Grocery List App</h1>
      <Header add={Add}/>
      <List set={setList} lst={list} chg={Change} del={Delete} />
    </div>
  );
}

export default App;

下面的代码是我的list.js文件。我正在遍历列表状态并为每个项目创建单独的“卡片”。

import React from 'react';
import Card from './item';

const List = (props) => {
    const productChange = (txt, v) => {
        console.log(props.lst[v].product)
    }
    const quantityChange = () => {
    }
    const cartChange  = () => {
    }
    return(
        <div>
            <p>To Find:</p>
            <ul>
                { props.lst.map((item, index) => 
                  item.cart === false ?
                    <Card 
                     key={item.index}
                     index={index}
                     value={index}
                     cart={item.cart}
                     item={item.product} 
                     units={item.quantity}
                     unitType={item.type} 
                     cartChange={cartChange}
                     itemChange={productChange}
                     quantityChange={quantityChange}
                     change={props.chg}
                     delete={props.del}/>
                  : null)
                }
            </ul>
            <p>Found</p>
            <ul>
                { props.lst.map((item, index) => 
                  item.cart === true ? 
                   <Card 
                    key={item.index}
                    index={index}
                    value={index}
                    cart={item.cart}
                    item={item.product} 
                    units={item.quantity}
                    unitType={item.unit} 
                    cartChange={cartChange}
                    itemChange={productChange}
                    quantityChange={quantityChange}
                    change={props.chg}
                    delete={props.del}/>
                   : null)
                }
            </ul>
        </div>
    )
}
export default List;

这是item.js的代码。这是我从列表中显示信息的最后一个位置。注意:当我更改输入文本时,第一个文件的change()在这里被调用。

import React from 'react';
const Card=(props)=>{
    return (
        <li key={props.value}>
            <div>
                <input 
                  type="checkbox"
                  checked={props.cart}
                  onChange={(e)=> {props.cartChange(props.value)}} />
            </div>
            <div>
                <input 
                 id={'product '+ props.value}
                 className='update' 
                 type='text'
                 value={props.item} 
                 onChange={(e) => 
                       props.change(props.value,'product', e.target.value)
                 }
                 />
                <br/>
                <input 
                  id='quantityValue' 
                  className='update' 
                  type='number'
                  value={props.units} 
                // onChange={(e)=> 
                    props.quantityChange(e.target.value, props.value)}
                 />
                <span id='quantityType' className='update'>{props.unitType} 
                </span>
            </div>
            <div>
                <button
                 id='save-button'
                 type='button' 
                 onClick={(e) => { props.change(
                                     props.item,
                                     props.units,
                                     props.unitType,
                                     props.value)
                                  }
                  }>&#10003; save</button>
                <button
                 id='delete-button'
                 type='button'
                 onClick={(e) => {props.delete(props.value)}}>&#10007; delete</button>
            </div>
        </li>
    )
}
export default Card;

2 个答案:

答案 0 :(得分:3)

您要调用setList并带有一个列表,在该列表中您只需修改一个对象。 您可以为此使用list.map()。理想情况下,您想向您的对象添加ID字段。

但是即使没有ID,您也可以使用索引:

setList(list.map((product, index)=>{index == i ? v : product}))

或更详细:

const Change = (i, txt, v) =>{
    const newList = list.map((product, index) => {
        return index == i ? v : product
    });
    setList(newList);
}

答案 1 :(得分:0)

您要实现change功能。是这样吗?

尝试这个。

  const Change = (i,txt,v) =>{
    setList(list.map((e, ei) => {
        if (ei === i) {
            e.product = v;
            return e;
        }
        return e;
    }));
  }