Salesforce LWCデコレータまとめ

# これは何？
この記事は「[24日後に立派なSalesforceエンジニアになるWEBエンジニア Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kakakaori)」の10日目の記事です。１5日後に立派なSalesforceエンジニアになるために今日はLightning Web Component (LWC)のデコレータについて見ていきたいと思います。

# デコレータの種類
[公式のドキュメント](https://developer.salesforce.com/docs/component-library/documentation/ja-jp/lwc/lwc.reference_decorators)も用意されていますがLWCには以下の3つのデコレータが用意されており、これらは変数や関数につけることができる。利用する際はjsにインポートしておく必要がある。

```javascript:test.js
import { LightningElement, api, track, wire } from 'lwc';
```

## `@api`
`@api`デコレータは他コンポーネントへ公開するときに使う。
つまり`@api`デコレータをつけた変数や関数は他コンポーネントからのアクセスができるようになる。

### サンプル
![ezgif-4-0ac95e9e97.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/4b75b7f9-da99-40bf-884c-73c3ae2dbc3e.gif)
```javascript:parent.js
import { LightningElement } from 'lwc';

export default class Parent extends LightningElement {
    name = "";
    
    onChange(event){
        this.name = event.target.value;
    }
}
```
```html:parent.html
<template>
    <!-- 子コンポーネントに自身のnameを渡す -->
    <c-child child-name={name}></c-child> 
    <lightning-input label="名前" onchange={onChange}></lightning-input>
</template>
```

```javascript:child.js
import { api, LightningElement } from 'lwc';

export default class Child extends LightningElement {
    @api
    childName; // この変数を親コンポーネントから変更できるようにしている
}
```
```html:child.html
<template>
    <div class="slds-p-horizontal_small">
        <p>{childName}</p>
    </div>
</template>
```

## `@track`
`@track`デコレータは元々、値が変更されたときに再描画するのに使われる。

### サンプル
![ezgif-2-77c9d3b0af.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/e3a98168-e87e-23e1-96f9-beb9ffd461c0.gif)
```javascript:test.js
import { LightningElement, track } from 'lwc';

export default class Test extends LightningElement {
    @track fullName = { firstName : '', lastName : '' };

    onChange(event) {
        this.fullName.firstName = event.target.value;
    }
}
```
```html:test.html
<template>
    <lightning-card icon-name="standard:account">
        <div class="slds-p-horizontal_small">
            <p>{fullName.firstName}</p>
            <p><lightning-input label="名前" onchange={onChange}></lightning-input></p>
        </div>
    </lightning-card>
</template>
```

### 補足
[Salesforce Spring ’20 のリリース](https://help.salesforce.com/s/articleView?id=release-notes.rn_lwc_track.htm&type=5&release=224)でなくても再描画されるようになった。ただリリースノートにあるように`@track`をつけないと再描画されないケースがある。

`@track`がついていない場合フレームワークは項目自体に新しい値が割り当てられる変更を監視して、変更があった場合はコンポーネントの該当箇所を再描画する。例えば先ほどのサンプルで以下のように変数そのものに新しい値を代入すると再描画が走る。
```javascript:test.js
this.fullName = { firstName : 'John', lastName : 'Doe' };
```
しかし、以下のように変数の中の1つのプロパティのみ変更された場合は再描画されない。
```javascript:test.js
this.fullName.firstName = 'John';
```
このような場合も再描画させる必要がある時は `@track fullName`　のようにデコレータをつけて宣言をする。

## `@wire`
 `@wire` デコレータはワイヤーサービスからデータの取得をするときに使う。`getRecord`やApexのメソッドでデータをとってきてjsの変数に紐づけるケースでよく使う。

### サンプル
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/fb4040e0-4ee5-8c76-76dd-1d8388787f01.png" width="400">

```javascript:test.js
import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
const FIELDS = ['Account.Name'];

export default class Test extends LightningElement {
    @api recordId;

    @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
    account;
}
```
```html:test.html
<template>
    <lightning-card icon-name="standard:account">
        <template if:true={account.data}>
            <div class="slds-p-horizontal_small">
                <p>{account.data.fields.Name.value}</p>
            </div>
        </template>
    </lightning-card>
</template>
```

# まとめ
- コンポーネント間でデータをやり取りするのが `@api`
- htmlとjs間でデータをやり取りするのが `@track`
- jsとApex間もしくはjsと`uiRecordApi.getRecord`間でデータをやり取りするのが `@wire`

# 最後に
今日はLWCのデコレータについてそれぞれの使い方をまとめていきました。
明日はLWCのxmlで設定する内容についてみていきます。