繁体   English   中英

无法使用 setState 在反应 js 中更新 object 的特定属性

[英]Cannot update particular property of object in react js using setState

我正在获取数据,并且我已映射数据以显示它。 一切都很好,但是当我尝试更新获取的数据(我已经存储在一个数组中,只是想通过其他方式更改它,下面提到)没有更新。我已经给出了下面的数据,我只是想改变当我单击按钮时,每个 object 的“数量”属性分别但每次我尝试使用扩展运算符并给出逗号并尝试在此处定义映射对象的“数量”属性时,它不会更新数量属性并替换整个数组。你能告诉我如何编写一个 onClick function 复制整个数组(使用扩展运算符)然后更新数量属性。(获取的数据存储在一个数组中)

0: {id: 11, ordered: true, quantity: 5, user: 1, item: {…}}
1: {id: 12, ordered: true, quantity: 1, user: 1, item: {…}}
2: {id: 14, ordered: true, quantity: 1, user: 1, item: {…}}
3: {id: 15, ordered: true, quantity: 4, user: 1, item: {…}}
4: {id: 17, ordered: true, quantity: 3, user: 1, item: {…}}

这是我正在获取的数据。(上图)

0:
    id: 11
    item: {id: 10, title: "Watch", image: "https://github.com/divanov11/django_ecommerce_mod5/blob/master/static/images/watch.jpg?raw=true", price: "$20"}
    ordered: true
    quantity: 5
    user: 1

这是每个对象中的数据(上图)。我想保持一切不变,只是分别更改每个 object 的数量属性。下面是我的代码。

import React, { useEffect, useState } from 'react';

let Cart = () => {

    let [myItems, setMyItems] = useState([])

    let fetchData = () => {
        fetch('http://127.0.0.1:8000/api/get-order-item/' + sessionStorage.getItem('id'), {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer' + ' ' + sessionStorage.getItem('token')
            }
        }).then(
            (response) => {
                return response.json()
            }
        ).then(
            (data) => {
                if (data) {
                    setMyItems(data)
                }
            })
    }

    useEffect(
        () => {
            fetchData()
            console.log(myItems)
        }, []
    )



    return (
        <div>
            {
                myItems.map(
                    (value) => {
                        return (
                            <div className='row  w-100 m-auto' >
                                <div className="card-deck container-fluid m-auto bg-light">
                                    <div className="card  bg-light mt-4 mb-2 " >
                                        <img src={value.item.image} className="card-img-top" alt="..." />
                                        <div className="card-body border-top ">
                                            <div className='d-flex justify-content-between' >
                                                <h4>{value.item.title}</h4>
                                                <div className='d-flex flex-row-reverse' >
                                                    <svg onClick={ () => { setMyItems( (prevState) => { return [...prevState , {value : { quantity : prevState.quantity - 1 }}  ] } )  } } id='add' xmlns="http://www.w3.org/2000/svg" width="28" height="23" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16" >
                                                        <path fill-rule="evenodd" d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
                                                    </svg>
                                                    <input defaultValue={value.quantity} className='w-25 h-75 text-center' />
                                                    <svg onClick={() => { console.log(myItems) }} xmlns="http://www.w3.org/2000/svg" width="32" height="25" fill="currentColor" class="bi bi-dash" viewBox="0 0 16 16">
                                                        <path fill-rule="evenodd" d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z" />
                                                    </svg>
                                                </div>
                                            </div>
                                            <h5>{value.item.price}</h5>
                                            <div class="form-check d-flex  justify-content-between">
                                                <input type="checkbox" class="form-check-input" id="quantity" checked={value.ordered} />
                                                <label class="form-check-label" for="exampleCheck1">Proceed this item to checkout</label>
                                                <button type="button" class="btn btn-success ">Save changes</button>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div >
                        )
                    }
                )
            }
        </div >
    )


}

export default Cart;

在 map function 内部,我正在映射对象,我只想创建一个按钮来更改它们各自对象的数量属性

尝试是:

setMyItems( (prevState) => { return [...prevState , {value : { quantity : prevState.quantity - 1 }}  ] } )  } }

首先,这很难内联阅读,所以我将其移至 function 以便您了解您正在使用的内容。

接下来,不是...prevState ,它传播整个前一个数组并附加一个带有{value: ...}的新尾部,而是通过索引或 id 找到您想要变异的项目(某种特定于应用程序的决定 -可能 id 更好)并将数组分成三部分:

  • 数组前面从0到i
  • 我们要更改数量的项目, i
  • 数组后面从i + 1到末尾

这可以通过切片和扩展来构建一个新数组来完成:

const newArr = [...arr.slice(0, i), arr[i], ...arr.slice(i + 1)];

最后一步:操作arr[i] object 来调整数量。 看起来数量在顶层,所以:

{...arr[i], quantity: newQuantity}

综上所述,这是一个可应用于代码的最小可运行示例:

 <script type="text/babel" defer> const {useEffect, useState} = React; const mockItems = [ {id: 11, quantity: 5, item: {title: "foo"}}, {id: 12, quantity: 1, item: {title: "bar"}}, {id: 14, quantity: 1, item: {title: "baz"}}, {id: 15, quantity: 4, item: {title: "quux"}}, {id: 17, quantity: 3, item: {title: "corge"}}, ]; fetch = () => new Promise((resolve, reject) => setTimeout(() => resolve({json: async () => mockItems}), 1000) ); const Cart = () => { const [items, setItems] = useState([]); useEffect(() => { (async () => { const response = await fetch("some endpoint"); setItems(await response.json()); })(); }, []); const setQuantity = (id, quantity) => { const i = items.findIndex(e => e.id === id); setItems(prev => [...prev.slice(0, i), {...prev[i], quantity}, ...prev.slice(i + 1), ]); }; return ( <ul> {.items?length. "loading..:". items.map(e => <li key={e.id}> <div>{e.item:title}</div> <div> Qty. {e.quantity} <button onClick={() => setQuantity(e,id. e.quantity + 1) } >+</button> <button onClick={() => setQuantity(e,id. e;quantity - 1) } >-</button> </div> </li> ) } </ul> ); }. ReactDOM,render(<Cart />. document;body): </script> <script src="https.//cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min:js"></script> <script src="https.//cdnjs.cloudflare.com/ajax/libs/react/16.10.0/umd/react.production.min:js"></script> <script src="https.//cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.0/umd/react-dom.production.min.js"></script>

暂无
暂无

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

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