Lightning 웹 구성 요소 오류 : [프록시의 'set': 트랩이 속성 '0'에 대해 거짓을 반환했습니다.]

Aug 18 2020

제품을 추가 한 다음 제거 할 수있는 카트를 만들려고합니다. 그러나 제거하면 오류가 발생 ['set' on proxy: trap returned falsish for property '0']합니다.

내 구성 요소 ParentComponent에서 제품을 선택하고 어레이에 추가합니다 cartItems. 각 카트 항목에 대해 호출 된 하위 구성 요소 cartRowItem가 인스턴스화됩니다. 아래 코드를 참조하십시오.

parentComponent.html :

<template>
    <div class="slds-grid slds-gutters">
            <lightning-card class="slds-col slds-size_1-of-3" title="Product Search">
                <div class="slds-grid slds-gutters">
                    <div class="slds-col slds-size_2-of-3 slds-var-m-left_small">
                        <lightning-input type="text" placeholder="Search for a product" value={productSearchKey} onchange={handleSearchKeyChange}></lightning-input>
                    </div>
                    
                    <div class="slds-col slds-size_1-of-3">
                        <button class="slds-button slds-button_brand slds-button_stretch slds-var-m-right_small" onclick={doSearch}>Search</button>
                    </div>
                </div>

                <template if:true={products}>
                    <lightning-datatable
                        key-field="id"
                        data={products}
                        columns={columns}
                        onrowaction={addToCart}
                        hide-checkbox-column>
                    </lightning-datatable>
                </template>
                
            </lightning-card>

        <lightning-card class="slds-col slds-size_2-of-3" title="Product Cart">
            <template for:each={cartItems} for:item="item">
                <c-cart-row-item key={item.id} cart-item={item} cart-items={cartItems} oncartitemremove={handleRemove}></c-cart-row-item>
            </template>
        </lightning-card>
    </div>
</template>

parentComponent.js :

import { LightningElement, api, track } from 'lwc';
import findProducts from '@salesforce/apex/TechDocSelfServeController.findProducts';

const tableColumns = [{
    label: 'Product Code',
    fieldName: 'ProductCode',
    type: 'text',
    sortable: true
},
{
    label: 'Product Name',
    fieldName: 'Name',
    type: 'text',
    sortable: 'true'
},
{
    label: 'Add to Cart',
    type: 'button-icon',
    
    typeAttributes: 
    {
        iconName: 'utility:add',
        name: 'addToCart',
        title: 'addToCart',
        disabled: false,
        alternativeText: 'Add to Cart',
    }
}];

export default class TechDocSelfServe extends LightningElement {
    products; 
    @api cartItems = [];
    columns = tableColumns;
    productSearchKey = '';
    error;
    
    doSearch() {
        let productSearchKey = this.productSearchKey;
        findProducts({ productSearchKey })
            .then((result) => {
                this.products = result;
                this.error = undefined;
            })
            .catch((error) => {
                this.error = error;
                this.products = undefined;
            });
    }

    addToCart(event) {
        const row = event.detail.row;
        this.cartItems = [...this.cartItems, row];
    
        const selectedEvent = new CustomEvent("cartitemadd", {
            detail: this.cartItems
        });

        console.log('cartItems on add -> ' + JSON.stringify(this.cartItems, null, 4));

        this.dispatchEvent(selectedEvent);
    }

    handleSearchKeyChange(event) {
        this.productSearchKey = event.target.value;
    }

    handleRemove(event) {
        this.cartItems = event.detail
    }
}

cartRowItem.html :

<template>
    <template if:true={displayRow}>
        <div class="slds-var-m-around_xx-small slds-box">
            <lightning-card>
                <div class="slds-text-heading_large slds-text-align_center "><u>{cartItem.Name}</u></div>
                    <lightning-button variant="destructive" label="Remove Item" title="RemoveItem" onclick={handleRemove} value={cartItem} class="slds-align_absolute-center"></lightning-button>
            </lightning-card>    
        </div>
    </template>
</template>

cartRowItem.js (Rahul 주석에 따라 업데이트 됨) :

import { LightningElement, api } from 'lwc';

export default class CartRowItem extends LightningElement {
    @api cartItem;
    _cartItems;
    displayRow = true;

    @api get cartItems() {
        return this._cartItems;
    }

    set cartItems(value) {
        this._cartItems = value;
    }

    handleRemove(event) {
        console.log('Should remove here.')
        var array = this._cartItems;
        var key = event.target.value.Id;
        var index = array.findIndex(function(item, i) {
            return item.Id === key
        });

        array.splice(index, 1);
        this._cartItems = array;

        console.log('cartItems after remove -> ' + JSON.stringify(this._cartItems, null, 4));
        
        const selectedEvent = new CustomEvent("cartitemremove", {
            detail: this._cartItems
        });

        this.dispatchEvent(selectedEvent);
        this.displayRow = false;
    }
}

cartRowItem에서 Remove 버튼을 누르면 제거 ['set' on proxy: trap returned falsish for property '0']하려는 배열의 항목에 따라 끝에 숫자가 변경 되는 오류가 표시 됩니다.

답변

2 rahulgawale Aug 18 2020 at 21:35

상위 제품에 의해 설정된 속성은 변경할 수 없습니다. 즉, 수정할 수 없습니다. 공용 속성에 대해 getter setter를 사용해야합니다.

_cartItems;
...

@api
get cartItems(){
    return this._cartItems;
}

set cartItems(value){
    this._cartItems = JSON.parse(JSON.stringify(value));
}

다른 이름으로 새 개인 속성을 만들었습니다 _cartItems.

이제 모든 작업을 수행하고 _cartItems. 업데이트 된 데이터를 부모로 보내려면 자식에서 사용자 지정 이벤트를 전달해야합니다.