問題の分析
LWC(Lightning Web Component)でApexから取得したデータを操作しようとすると、「Uncaught TypeError: 'set' on proxy: trap returned falsish for property」というエラーが発生しました。このエラーの原因は、@wireデコレータを使用して取得したデータが読み取り専用(read-only)であり、直接変更することができないためです。
解決策
この問題を解決するには、データを直接操作するのではなく、クローンを作成してそれを変更する必要があります。以下に修正済みのコードを示します。
修正済みコード
HTML:
<template>
<template if:true={wiredContact}>
{wiredContact.Name}
<lightning-input value={wiredContact.Name} onchange={updateName}></lightning-input>
</template>
</template>
JavaScript:
import { LightningElement, wire, track } from 'lwc';
import myContact from '@salesforce/apex/ContactController.fetchContact';
export default class Myrefreshapextest extends LightningElement {
@track wiredContact;
@wire(myContact)
fetchedContact({ error, data }) {
if (data) {
console.log(JSON.stringify(data));
// データをクローンして操作可能にする
this.wiredContact = { ...data };
} else if (error) {
console.error(error);
}
}
updateName(event) {
const newName = event.detail.value;
console.log('New Name:', newName);
console.log('Current wiredContact:', JSON.stringify(this.wiredContact));
// 名前フィールドを更新した新しいオブジェクトを作成
this.wiredContact = {
...this.wiredContact,
Name: newName
};
}
}
Apex:
public class ContactController {
@AuraEnabled(cacheable=true)
public static Contact fetchContact() {
return [SELECT Id, Name FROM Contact LIMIT 1];
}
}
修正ポイントの解説
スプレッド構文
{ ...data }を使用したクローン作成:@wireデコレータで取得したデータは読み取り専用のため、そのまま操作するとエラーになります。スプレッド構文を使用して新しいオブジェクトを作成することで、この問題を回避しました。updateNameで新しいオブジェクトを作成:wiredContactを直接変更せず、更新したデータを反映した新しいオブジェクトを作成しました。@trackの使用:@trackを使用してwiredContactプロパティの変更を検知し、コンポーネントを再描画可能にしました。
補足情報
深いネスト構造のクローン:
オブジェクトが深くネストされている場合は、JSON.parse(JSON.stringify(data))またはstructuredClone(data)を使用すると安全にクローンできます。ただし、後者はブラウザのサポート状況に注意が必要です。@trackの必要性:
最新のLWCでは、オブジェクト全体を再割り当てする場合、明示的な@trackは不要ですが、複雑な状況では利用する価値があります。
この修正を適用することで、「set on proxy」エラーを回避し、wiredContactオブジェクトのフィールドを安全に更新できるようになります。
コメント
コメントを投稿