〜エンジニア初学者の開発日記〜 一の巻

こんにちは、つかさです
久しぶりの投稿になりますが、今回は現在携わっている開発で学んだことを記事にまとめようと思います！:grin:

### 前提
- バックエンド
👉 Laravel
- フロントエンド
👉 Inertia.js(Vue3)

## useForm(Inertia.js)
フォーム操作を簡単に管理するための便利なヘルパー関数
このヘルパー関数を使用することで、`状態管理`、`バリデーションエラーの取得`、`フォーム送信`、`リセット`などを簡単に行うことができます。

#### 基本
```js:useFrom
import { useForm } from '@inertiajs/vue3';

export default {
  setup() {
    const form = useForm({
      name: '', //フォームデータはオブジェクト形式で定義。
      email: '',
      password: '',
    });

    const submit = () => {
      form.post('/register'); 
      // 送信メソッド（post, put, patch, delete など）を指定して簡単にAPIリクエストを送信可能。
    };

    return { form, submit };
  },
};
//自動的にCSRFトークンが付与されるため、Laravelとの連携がスムーズ。
```
#### 主要な機能
```js:useForm
//フォームを初期状態に戻せます。
const form = useForm({
  name: '',
  email: '',
});

form.reset();

//useFormを使用しなかった場合
const form = reactive({
  name: '',
  email: '',
});

const resetForm = () => {
  form.name = '';
  form.email = '';
};
```
```js:useForm
//サーバー側で発生したバリデーションエラーに対して簡単にアクセス可能です。
form.post('/register', {
//リクエスト後の処理を定義できる
  onSuccess: () => {
    alert('登録が完了しました！');
  },
  onError: () => {
    console.log(form.errors); 
  },
});

// エラーの表示
<div v-if="form.errors.name">{{ form.errors.name }}</div>

//useFormを使用しなかった場合
const form = reactive({
  name: '',
  email: '',
});

const errors = reactive({});

const submitForm = async () => {
  try {
    await axios.post('/register', form);
  } catch (error) {
    if (error.response && error.response.data.errors) {
      Object.assign(errors, error.response.data.errors);
    }
  }
};

// エラーの表示
<div v-if="errors.name">{{ errors.name }}</div>


//プロパティでリクエスト中かどうかを判定できます。
<form @submit.prevent="form.post('/register')">
  <button :disabled="form.processing">送信</button>
</form>

//useFormを使用しなかった場合
const isLoading = ref(false);

const submitForm = async () => {
  isLoading.value = true;
  try {
    await axios.post('/register', form);
  } finally {
    isLoading.value = false;
  }
};

<button :disabled="isLoading">送信</button>
```
## script setup(Vue3)
コードを簡潔に、そのまま変数や関数がテンプレートで利用可能になるため、よりシンプルに記述できるようになった。
```vue:script setup
//従来
<script>
import { useForm } from '@inertiajs/vue3';

export default {
  setup() {
    const form = useForm({
      name: '',
      email: '',
    });

    const submit = () => {
      form.post('/register');
    };

    return { form, submit }; // テンプレートで使用するには必須
  },
};
</script>

//script setupを使用した場合
<script setup>
import { useForm } from '@inertiajs/vue3';

const form = useForm({
  name: '',
  email: '',
});

const submit = () => {
  form.post('/register');
};
</script>
```
## usePage(Inertia.js)
用途は大きく3つに分類することが出来ます。
- プロパティの取得
- 現在のページ情報の取得
- 動的に取得したデータを監視
***

#### 1. Props（プロパティ）の取得
Inertia.js では、サーバー側から渡されたデータが props に格納され、フロントエンドで直接データを利用することが可能。

```php:usePage
return Inertia::render('Dashboard', [
    'user' => Auth::user(),
    'notifications' => Notification::all(),
]);
```

```vue:usePage
<script setup>
import { usePage } from '@inertiajs/vue3';

    const { props } = usePage();
    const user = props.value.user;
    const notifications = props.value.notifications;

    console.log(user, notifications);
  };
</script>
```

#### 2. 現在のページ情報の取得
現在のページに関するメタデータを取得できる。
```vue:usePage
import { usePage } from '@inertiajs/vue3';

<script setup>
    const { url, component } = usePage().value;

    console.log(`URL: ${url}`); // 現在の URL
    console.log(`コンポーネント: ${component}`); // 現在のコンポーネント名
  },
</script>
```
#### 3. 動的に取得したデータを監視
リアクティブなデータとして、usePage のプロパティを監視することが可能
```vue:usePage
<script setup>
import { usePage } from '@inertiajs/vue3';
import { watch } from 'vue';

    const { props } = usePage();

    watch(() => props.value, (newProps) => {
      console.log('Props が変更されました:', newProps);
    });
  },
};
  },
</script>
```
## defineProps(vue3)
用途は大きく2つに分類することが出来ます。
-  型定義を行う
- オプションとしてデフォルト値を指定する
***

#### 基本
```vue:defineProps
<script setup>
defineProps(['message', 'count']);
</script>

<template>
  <p>{{ message }} - {{ count }}</p>
</template>
```

#### 1. 型定義を行う
TypeScript と組み合わせて使うと、props に対して型定義を行うことができます。これにより、静的型チェックが可能になり、コードの品質を保つことができます。
```vue:defineProps
<script setup lang="ts">
defineProps<{
  message: string;
  count: number;
}>();
</script>

<template>
  <p>{{ message }} - {{ count }}</p>
</template>
```

#### 2. オプションとしてデフォルト値を指定する

```vue:defineProps
<script setup>
defineProps({
  message: {
    type: String,
    default: 'Hello, world!',
  },
  count: {
    type: Number,
    default: 0,
  },
});
</script>

<template>
  <p>{{ message }} - {{ count }}</p>
</template>
```

## definePropsとusePageの比較

実際に実装していく中で、`defineProps`しか定義していないvueファイルだとしてもサーバからのレスポンスデータを受け取り、利用することができます。上記では`usePage`を使用してサーバからのレスポンスデータを利用することが可能と説明しましたが、なぜ`defineProps`しか定義していないvueファイルでも利用できるのでしょうか？

<details><summary>答え</summary>

Vue ファイルで defineProps が定義されている場合、サーバから送られたデータは Inertia.js が自動的に props として渡しているからです。
</details>

#### 使い分け
- defineProps
基本的にサーバからのレスポンスを受け取るためには`defineProps`で十分です。理由としては以下２つが挙げられます。
👉シンプルで直感的
サーバから渡されるデータを Vue コンポーネント内で直接 props として受け取る設計は、Vue の基本的な仕組みと一致している
👉型付けも可能
TypeScript を使っている場合、defineProps で型を定義すれば型安全にデータを扱うことができる

- usePage
以下のような2つのケースでは`usePage`を使う方が便利です。
👉多くのデータを一括で扱いたい場合
👉共通のページデータにアクセスする場合
ページ共通のメタ情報や他の非表示データにアクセスする(認証など)

#### 結論
基本的には`defineProps`を使用し、必要に応じて`usePage`を補助的に使う形が効率的！
***

### まとめ

読んでいただきありがとうございました！
これからも自分のペースで記事を更新したり、新たな記事を書いていこうと思うので是非見ていただけたらなと思います！:grin: