💡

【イラスト付き】Nuxt3でWebAPIと状態管理【要点一気読み】

2024/08/31に公開

はじめに

皆さんこんにちは。

今回はNuxt単体での状態管理とWebAPIについてご紹介します。

Nuxtで状態の作成をするための関数、WebAPI呼び出しを行う関数それぞれが用意されています。それらを組み合わせて使うことで状態管理をすることができます。

こんな人にオススメ

  • NuxtでのWebAPI呼び出しの書き方を知りたい
  • Nuxtでの状態管理の書き方を知りたい

初めて学習する方にも分かるように、要点を絞って丁寧に解説していきます。

😋 Nuxtでの状態の扱い方をご紹介します♪

useStateで状態作成

まずポイントをチェック

  • リアクティブな値を生成可能
  • コンポーザブル関数と組み合わせて利用

Nuxtでリアクティブな値を生成するにはuseStateを利用します。useStateはSSRフレンドリーな関数であるため、Vue.jsのrefやreactiveではなくこちらを利用します。

useStateの書式は山カッコに扱う値のデータ型、第一引数にキー文字列、第二引数に初期値を返す関数を指定します。値はコンポーネント間で共有可能であり、キー文字列は別のコンポーネントから値を取り出す際に利用します。

const state = useState<>('キー', () => {return 初期値});

生成した値はscript内ではvalueプロパティから参照します。template内では.valueは必要ありません。

state.value
<template>
  {{state}}
</template>

useStateはコンポーザブル関数と組み合わせて使うことができます。状態とそれを操作する関数を一元管理することができます。useStateは初期化時のみ動作するため、コンポーザブル関数をコンポーネントで呼び出しても再レンダリングで状態が初期化されることはありません。

😋 useStateでリアクティブな値を生成します♪

useStateのシンプルなサンプルを掲載します。

components/state/Sample1.vue(コンポーネント内でstateを持つ例)
<template>
    <div>{{ state1 }}</div> <!-- stateの値を表示 -->
    <button @click="plus">state1++</button>
</template>
<script setup lang="ts">
const state1 = useState<number>("state1", () => 100); // stateを用意
const plus = () => state1.value++; // stateを更新する関数
</script>
components/state/Sample2.vue(別のコンポーネントのstateを参照する例)
<template>
    <div>{{ state1 }}</div>
    <button @click="plus">state1++</button>
</template>
<script setup lang="ts">
const state1 = useState<number>('state1'); // Sample1.vueのstate1を利用
const plus = () => state1.value++;
</script>
composables/useStore.ts(コンポーザブル関数でstateを管理する例)
type obj = { title: string };
export default () => {
    const objStore = useState<obj[]>("objState", () => [ // stateを用意
        { title: 'title1' },
        { title: 'title2' }
    ]);
    const addObj = (title: string) => objStore.value.push({ title }); // stateを操作する関数
    return { objStore, addObj };
};
State.vue(コンポーザブル関数のstateを利用する側)
<template>
    <div v-for="obj of objStore">
        <p>{{ obj.title }}</p>
    </div>
    <button @click="addObj(`title${objStore.length + 1}`)">addObj</button>
</template>
<script setup lang="ts">
const { objStore, addObj } = useStore(); //コンポーザブル関数からstate関連を取得
</script>

useFetchでWebAPI呼び出し

まずポイントをチェック

  • WebAPIとやり取りする
  • 戻り値は4種のデータ(data, error, pending, refresh)
    • data、errorはリアクティブな値

useFetchでWebAPI呼び出しを行えます。取得したデータはリアクティブな値になっています。そのためデータの再取得に応じて画面も再レンダリングされます。

useFetchの書式は山カッコに扱うデータ型、第一引数に送信先URL、第二引数にオプションをオブジェクトで指定します。useFetchの戻り値は4種類あり、必要なものを分割代入で受け取ります。

useFetch戻り値4種
1. data:WebAPIから取得したデータ
2. error:エラー情報
3. pending:通信中のフラグ
4. refresh :dataを再取得する関数

dataはWebAPIから取得したデータ、errorはエラーオブジェクト、pendingは通信状況を表す真偽値、refreshは再リクエストしデータを取得し直す関数です。

const { data, error, pending, refresh } = await useFetch<>(URL);

GETリクエストの場合はオプションオブジェクトは不要です。それ以外のリクエストを送る場合はオプションのmethodプロパティにリクエストメソッドを指定します。そしてbodyプロパティに送信するデータを指定します。

😋 useFetchでWebAPIを呼び出しを行います♪

useFetchのシンプルなサンプルを掲載します。

nuxt.config.ts(URLの共通部分を設定ファイルに定義)
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiHostAddress: 'http://localhost:3000'
    }
  }
});
Fetch.vue(GETで取得したデータ表示とPOSTでデータ登録する例)
<template>
    <div v-if="pending === true">loading...</div> <!-- レスポンスが来るまでloading -->
    <button @click="refresh()">reload</button> <!-- 再リクエストでdataを更新-->
    <button @click="postData('POSTSample')">POST</button>
    <div>-----</div>
    <h3>data一覧</h3>
    <p v-if="error">{{ JSON.stringify(error) }}</p> <!-- errorがあれば表示 -->
    <ul>
        <li v-for="item of items" :key="item.title">{{ item.title }}</li><!--dataを表示-->
    </ul>
</template>
<script setup lang="ts">
const runtimeConfig = useRuntimeConfig(); // 設定ファイルの読み取り
const { data: items, error, pending, refresh } = await useFetch<{ title: string }[]>(runtimeConfig.public.apiHostAddress +
    '/api/items'); // GETリクエストを送信
const postData = async (title: string) => {
    const { data } = await useFetch<{ title: string }>('/api/items', {
        baseURL: runtimeConfig.public.apiHostAddress,
        method: 'POST', // POSTリクエストを送信
        body: { title },
    });
    alert(data.value);
};
</script>

コンポーザブル関数で状態管理

まずポイントをチェック

  • useFetchとuseStateとコンポーザブル関数を組み合わせる
  • コンポーザブル関数にてstateを用意
  • useFetchで取得したデータはstateに保管する

コンポーザブル関数にstateとstateを操作する関数を配置することで、stateに関連する処理を一元管理でき、複数のコンポーネントでロジックを共有することができます。コンポーザブル関数のstateにはWebAPIから取得したデータを設定するようにします。

😋 コンポーザブル関数で状態と操作の関数を一元管理しています♪

useFetchとuseStateとコンポーザブル関数を組み合わせたシンプルなサンプルを掲載します。

useWebStore.ts(WebAPIのデータをstateとして管理するコンポーザブル関数)
type obj = { title: string };
export default () => {
    const titleStore = useState<obj[]>("titleState", () => []); // stateを用意
    const getAllTitle = async () => {
        const { data } = await useFetch<obj[]>('http://localhost:3000/api/items');
        if (data.value) {
            titleStore.value = data.value; //WebAPIからのデータをstateに保管
        }
    };
    getAllTitle(); // WebAPI からデータ取得

    const addTitle = (title: string) => {
        titleStore.value.push({title}); // stateを操作
    };
    return { titleStore, getAllTitle, addTitle };
};

おわりに

皆さん、お疲れ様でした。
ここまでご覧いただき、ありがとうございました。

NuxtにはWebAPI呼び出しや状態の用意のための関数が用意されています。Vue.jsの機能ではなくNuxtの機能を使うことになります。この記事を通して機能の輪郭を確認いただければ幸いです。

😋 これからもプログラミング学習頑張りましょう♪

参考リンク集(Nuxt公式のリンク)

Discussion