問題
@Sicut_studyさんの【図解解説】話題の神Reactフレームワークreact-serverで技術記事投稿サイトを開発するチュートリアル【@lazarv/react-server/Convex/TypeScript】
をやっていて、Convexがどう動いているのか分からなかったのでまとめます。
Convexとは
リアルタイムデータベースを中心にしたバックエンドサービスを提供するプラットフォームです。
やっていること
ConvexのProvider設定
src/app/ConvexClientProvider.tsx
src/app/ConvexClientProvider.tsx
"use client";
import { ConvexProvider, ConvexReactClient } from "convex/react";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL!);
export default function ConvexClientProvider({
children,
}: {
children: React.ReactNode;
}) {
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
}
アプリ内で、ConvexのConvexClientProviderを使えるようにする
src/app/(root).layout.tsx
import "./global.css";
import Header from "../components/Header";
import { Footer } from "../components/Footer";
import ConvexClientProvider from "./ConvexClientProvider";
export default function RootLayout({
pageName,
children,
}: React.PropsWithChildren<{
pageName: React.ReactNode;
}>) {
return (
<html lang="ja">
<body>
<ConvexClientProvider> // ConvexClientProviderを設定
<div className="flex flex-col min-h-screen">
<Header pageName={pageName} />
<main className="flex-grow">{children}</main>
<Footer />
</div>
</ConvexClientProvider>
</body>
</html>
);
}
ConvexのAPI作成
convex/artiles.ts
// Convex関数を作り、Convexと記事データをやり取りするファイル
// convexのコンソールから関数を確認できる
// v オブジェクト
// 引数やデータのバリデーションを行うためのさまざまなユーティリティ関数を提供
// クエリやミューテーションの引数が特定の型や条件を満たしているかどうかを検証
import { v } from "convex/values";
// query Getリクエスト
// mutation POSTリクエスト
import { mutation, query } from "./_generated/server";
// 中略
export const getPopular = query({
// get クエリはオプションの limit 引数を受け取る
// limit 引数が提供された場合、その値を使用して取得する記事の数を制限
// 提供されない場合は、すべての記事を取得
args: {
// limit 引数がオプションであり、数値型であることを指定
limit: v.optional(v.number()),
},
handler: async (ctx, args) => {
const { limit } = args;
const articles = await ctx.db.query("articles").collect();
const sortedArticles = articles
.sort((a, b) => (b.viewCount ?? 0) - (a.viewCount ?? 0))
// limit がある場合、その値を使用して配列の最初から limit の位置までの要素を抽出
// limit がない場合(null または undefined の場合)、デフォルトで最初から10個の要素を抽出
.slice(0, limit ?? 10);
return sortedArticles.map((article) => {
return {
id: article._id,
title: article.title,
description: article.description,
author: article.author,
createdAt: article._creationTime,
viewCount: article.viewCount,
};
});
},
});
// 中略
Convexのコンソールから関数を確認できる
トップページからGET.popular.server.tsを呼び出す
src/app/page.tsx
const getArticles = async () => {
// fetch は、JavaScriptの標準APIで、ネットワークリクエストを行うために使用される
const response = await fetch(
// 作成したAPIを叩く
// src/app/api/articles/GET.popular.server.tsを呼ぶ
"http://localhost:3000/api/articles/popular?limit=10",
);
// レスポンスをjson形式に変換
const data = await response.json();
return data;
};
export default async function Home() {
//中略
// PopularArticleList にarticlesを渡して描画
<PopularArticleList articles={articles} />
//中略
サーバーサイドレンダリング (SSR)でGET.popular.server.tsを呼び出す
src/app/api/articles/GET.popular.server.ts
import { ConvexClient } from "convex/browser";
import { api } from "../../../../convex/_generated/api";
// VITE_CONVEX_URL サーバーやAPIのURLを指し、ConvexClientの接続先を指定
const convexUrl = import.meta.env.VITE_CONVEX_URL;
if (!convexUrl) {
throw new Error("VITE_CONVEX_URL is not defined");
}
// ConvexClientクラスのインスタンスを作成
const client = new ConvexClient(convexUrl);
// request: Requestは、HTTPリクエストの情報を含むオブジェクト
export default async function GetBlogs(request: Request) {
// 中略
// JS標準のURL オブジェクトを作成
// リクエストのURLを解析して、クエリパラメータなどにアクセスできる
const url = new URL(request.url);
// 中略
// new Response 新しい Response オブジェクトを作成
const response = new Response(JSON.stringify(articles))
// console.log("response", response);
return response;
終わりに
Convexの動作を理解するのは難しかったですが、各コンポーネントのつながりがわかって勉強になりました。
参考
【図解解説】話題の神Reactフレームワークreact-serverで技術記事投稿サイトを開発するチュートリアル【@lazarv/react-server/Convex/TypeScript】