Home
back

Tanstack Start , full-stack 調査

id: 182, 2025-05-21

### 音声概要

・AIで生成された 音声概要になります。


### 概要

  • フルスタックの Tanstack Start 入門メモになります。
  • beta版みたいでした。
  • vinxi 採用してるみたい。
  • ルーティング: File based Route

[ 公開 2025/02/14 ]


### 構成

  • Tanstack Start
  • node 20
  • vite
  • vinxi

### 関連


### install


  • dev-start
npm run dev

### Vercel + Tanstack Start Deploy


### vercel


  • app.config.ts , server 部分を追加

  • github 経由で、vercel にデプロイできました。

// app.config.ts
import { defineConfig } from "@tanstack/start/config"

export default defineConfig({
  server: {
    preset: "vercel",
  },
})

  • routes/index.tsx
  • サンプルの、ファイル書込み処理を削除して。フロントのみに修正

// app/routes/index.tsx
import {useState}  from "react";
import { createFileRoute } from "@tanstack/react-router"

export const Route = createFileRoute("/")({
  component: Home,
})

function Home() {
  const [count, setCount] = useState(0);
  return (
  <>
    <h1>index.tsx</h1>
    <hr />
    <button
      type="button"
      onClick={() => {
        setCount(count + 1);
      }}
    >
      Add 1 to 0
    </button>
    count = {count}
    </>  
  )
}

### API POST , GET 通信

  • バックエンド API通信

  • GET 通信
  • app/routes/api/helloget.ts
import { json } from "@tanstack/start"
import { createAPIFileRoute } from "@tanstack/start/api"

export const APIRoute = createAPIFileRoute("/api/helloget")({
  GET: ({ request, params }) => {
    console.log("#GET /api/helloget")
    return json({ message: "Hello , /api/helloget" })
  },
})

  • POST 通信
  • app/routes/api/hello.ts
  • body: await request.json で受信
  • レスポンスに、body値を返す。
import { json } from "@tanstack/start"
import { createAPIFileRoute } from "@tanstack/start/api"

export const APIRoute = createAPIFileRoute("/api/hello")({
  POST: async ({ request, params }) => {
    const body = await request.json();
    return json({ 
      message: "Hello ,/api/hello POST-DATA" , data: body
    })
  },
})

  • front
  • app/routes/ApiTest.tsx
import { createFileRoute } from "@tanstack/react-router"

export const Route = createFileRoute("/ApiTest")({
  component: RouteComponent,
})

function RouteComponent() {

  const testProc = async function(){
    try{
      const response = await fetch(`/api/helloget`);
      if (!response.ok) throw new Error("error, /api/helloget");
      const data = await response.json();
      console.log(data);

      const postData = {id: 1, name: "name-post1"}
      const resPost = await fetch(`/api/hello`,
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(postData),
        }
      );
      if (!resPost.ok) throw new Error("error, /api/hello");
      const dataPost = await resPost.json();
      console.log(dataPost);
    }catch(e){console.error(e)}
 }

  return (
  <>
    <div className="text-3xl">ApiTest !</div>
    <hr className="my-2" />
    <button 
    className="btn"
    onClick={()=>testProc()}>Test</button>
  </>
  )
}

### SQLite3 + drizzle , Tanstack Start

  • sqlite3 + drizzle 使う例です。
  • CRUDサンプル的な例です。

### 書いたコード



### API

  • sqlite_1/app/routes/api/todos/list.ts
import { json } from "@tanstack/start"
import { createAPIFileRoute } from "@tanstack/start/api"
import {db} from "../../../../src/index";
import {todos} from "../../../../src/db/schema";

export const APIRoute = createAPIFileRoute("/api/todos/list")({
  GET: async ({ request, params }) => {
    const allTodos = await db.select().from(todos);

    return json({
      message: "Hello ,/api/hello POST-DATA",
      data: allTodos,
    })
  },
})

  • sqlite_1/app/routes/api/todos/create.ts
import { json } from "@tanstack/start"
import { createAPIFileRoute } from "@tanstack/start/api"
import {db} from "../../../../src/index";
import {todos} from "../../../../src/db/schema";

export const APIRoute = createAPIFileRoute("/api/todos/create")({
  POST: async({ request, params }) => {
    try{
      const body = await request.json();
      console.log(body);
      const title = body.title;
      if (!title) {
        return res.status(400).json({ message: "Title is required" });
      }
      const newTodo = await db.insert(todos).values({ title }).returning();
      return json({ message: "Hello "/api/todos/create"!" })
    }catch(e){
      console.error(e);
      return json({ message: "" })
    };
  },
})