【Salesforce】Lightning Web Components（LWC）でレコード更新検知を行う

## はじめに

この記事は、[以前の記事](https://qiita.com/kotaro-saito/items/bf6e8a91cb1ffc229615)の続きです。

前回はページ全体を再読み込みすることなく、レコードデータをリフレッシュする方法を説明しました。
しかし、リフレッシュが必要かどうかを判断することができませんでした。

そこで、本記事ではケースレコードの更新を検知し、リフレッシュが必要かどうかをコンポーネントに表示する方法を紹介します。

## 構築手順

1. プラットフォームイベントの構築
2. レコードトリガーフローの構築
3. Lightning Web Componentsの作成

## 1. プラットフォームイベントの構築

ケースレコードの更新を検知するために、まずはプラットフォームイベントを作成します。
今回は以下情報でプラットフォームイベントを作成します。

- オブジェクト名 : `CaseUpdateNotification`
- カスタム項目
    - 表示ラベル : `RecordId`
    - API名 : `RecordId__c`
    - データ型 : テキスト

![スクリーンショット 2025-03-05 17.55.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/768bd5a4-1f89-4f22-b8f5-8df0b0b49e1e.png)

## 2. レコードトリガーフローの構築

レコードトリガーフローを使用して、ケースが更新された際にプラットフォームイベントを発火します。

- 開始を設定
    - 対象オブジェクト : ケース
    - トリガー条件 : レコードが更新された
    - エントリ条件 : なし

![スクリーンショット 2025-03-05 17.58.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/45d663d3-7990-4c32-8827-77eb95d5071a.png)

- レコードを作成
    - オブジェクト : `CaseUpdateNotification__e`
    - 項目値
        - 項目 : `RecordId`
        - 値 : `{!$Record.Id}`

![スクリーンショット 2025-03-05 18.00.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/a4112ea1-abd4-4e1a-9d71-37a4d475b679.png)

最終的なフローは以下のようになります。

![スクリーンショット 2025-03-05 18.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/e27ee71c-328d-40f0-9050-2af00fc74707.png)

## 3. Lightning Web Componentsの作成

`caseDetails.html` は以下のように設定します。

```caseDetails.html
<template>
    <lightning-card title="ケースの詳細" icon-name="standard:case">
        <div class="slds-m-around_medium">
            <div style="text-align:right;">
                <!-- isUpdateAvailableがtrue（ケースの更新を検知した場合）に文言表示を行う -->
                <template if:true={isUpdateAvailable}>
                    <p class="slds-m-left_x-small slds-text-color_error">レコードの更新があります</p>
                </template>
                <lightning-button-icon onclick={handleRefresh} icon-name="utility:refresh"></lightning-button-icon>
            </div>
            <lightning-record-form object-api-name="Case" record-id={recordId} layout-type="Full" columns="2" mode="view"></lightning-record-form>
        </div>
    </lightning-card>
</template>
```

`caseDetails.js` では、プラットフォームイベントの購読とレコード更新の検知を管理します。

```caseDetails.js
import { LightningElement, api, wire } from 'lwc';
import { subscribe, unsubscribe, onError, setDebugFlag, isEmpEnabled } from 'lightning/empApi';
import { notifyRecordUpdateAvailable } from 'lightning/uiRecordApi';

export default class CaseDetails extends LightningElement {
    @api recordId;
    isUpdateAvailable = false;
    // ケース更新イベントの登録を行うプラットフォームイベント
    channelName = '/event/CaseUpdateNotification__e';
    subscription = {};

    connectedCallback() {
        this.handleSubscribe();
    }

    disconnectedCallback() {
        this.handleUnsubscribe();
    }

    handleSubscribe() {
        const messageCallback = (response) => {
            const eventRecordId = response.data.payload.RecordId__c;
            // 対象のケースIDとプラットフォームイベントに登録されたケースIDが一致した場合
            // コンポーネントに文言表示を行うようisUpdateAvailableをtrueとする
            if (eventRecordId === this.recordId) {
                this.isUpdateAvailable = true;
            }
        };

        // トリガーフローでプラットフォームイベントが発火された際に、messageCallbackを起動
        subscribe(this.channelName, -1, messageCallback).then(response => {
            this.subscription = response;
        });
    }

    handleUnsubscribe() {
        unsubscribe(this.subscription, response => {
            this.subscription = null;
        });
    }

    handleRefresh() {
        notifyRecordUpdateAvailable([{recordId: this.recordId}]);
        // リフレッシュ後、文言が非表示とするためisUpdateAvailableをfalseにする
        this.isUpdateAvailable = false;
    }
}

```

## 実際の画面

ケースレコードのリフレッシュが必要な場合、「レコードの更新があります」という通知が表示されます。

![更新検知.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/bcc95d76-c17b-433f-9860-1605951f9815.gif)