【Drizzle ORM】NextJs14 と Drizzle ORM【#19 TanStack Query UseQuery】

2024/08/27に公開

【#19 TanStack Query UseQuery】

YouTube: https://youtu.be/sdVWJ6x9b04
https://youtu.be/sdVWJ6x9b04

今回は「useQuery」を使用して、
現在データベースに登録されているユーザーのデータを取得します。

https://tanstack.com/query/latest/docs/framework/react/guides/queries

データの取得時に以前作成した
Honoのクライアントを使用します。

lib/hono.ts
import { hc } from "hono/client";
import { AppType } from "@/app/api/[[...route]]/route";

export const client = hc<AppType>(process.env.NEXT_PUBLIC_APP_URL!);
.env.local
NEXT_PUBLIC_APP_URL=http://localhost:3000

こちらが設定されていることが確認できましたら、
ユーザー取得のhooksを作成します。

hooks/users/use-get-users.ts
import { useQuery } from "@tanstack/react-query";

import { client } from "@/lib/hono";

export const useGetUsers = () => {
  const query = useQuery({
    queryKey: ["users"],
    queryFn: async () => {
      const response = await client.api.users.$get();

      if (!response.ok) {
        throw new Error("Failed to fetch users");
      }

      const { data } = await response.json();

      return data;
    },
  });

  return query;
};

上記の「reutrn data」に対応させるため、
以下の部分を修正します。

    return c.json({
      users: data,
    });
app/api/[[...route]]/users.ts
import { Hono } from "hono";
import { z } from "zod";
import { zValidator } from "@hono/zod-validator";
import { clerkMiddleware, getAuth } from "@hono/clerk-auth";

import { db } from "@/db/drizzle";
import { users } from "@/db/schema";
import { eq } from "drizzle-orm";

const app = new Hono()
  .get("/", async (c) => {
    const data = await db.select().from(users);

    return c.json({
      data,
    });
  })
  .get("/me", clerkMiddleware(), async (c) => {
    const auth = getAuth(c);

    if (!auth?.userId) {
      return c.json({ error: "Unauthorized" }, 401);
    }

    const [data] = await db
      .select()
      .from(users)
      .where(eq(users.clerkId, auth.userId));

    if (!data) {
      return c.json({ error: "User not found" }, 404);
    }

    return c.json({ user: data });
  })
  .get(
    "/:id",
    zValidator(
      "param",
      z.object({
        id: z.string(),
      })
    ),
    async (c) => {
      // const id = c.req.param("id");
      const { id } = c.req.valid("param");

      const [data] = await db.select().from(users).where(eq(users.id, id));

      if (!data) {
        return c.json({ error: "User not found" }, 404);
      }

      // if (data.length === 0) {
      //   return c.json({ error: "User not found" }, 404);
      // }

      return c.json({
        user: data,
      });
    }
  );

export default app;

ここまでできましたら、
アプリのトップページで
ユーザーデータ取得のテストを行います。

app/page.tsx
"use client";

import { useGetUsers } from "@/hooks/users/use-get-users";

export default function Home() {
  const usersQuery = useGetUsers();
  const users = usersQuery.data || [];

  const isLoading = usersQuery.isLoading;

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div>
        {isLoading ? (
          <p>Loading...</p>
        ) : (
          users.map((user) => <div key={user.id}>{user.name}</div>)
        )}
      </div>
    </main>
  );
}

Discussion