メインコンテンツまでスキップ

第07章:Workers APIとつないでみよう 🔗

この章では、React の画面と Cloudflare Workers の API を、はじめてちゃんとつなぎます 😊 Cloudflare の現在の公式導線では、React SPA + Workers API + Cloudflare Vite plugin をひとつの流れで扱う構成が案内されていて、React 側から Worker の /api/ を呼ぶ形が基本です。React 公式ドキュメント側も、現行の最新系は React 19.2 を案内しています。(Cloudflare Docs)


この章のゴール 🎯

この章が終わるころには、こんな流れが自分で書けるようになります ✨

  • 画面のボタンを押す
  • React から fetch()/api/hello を呼ぶ
  • Worker が JSON を返す
  • その結果を画面に表示する

ここで大事なのは、React は見た目担当、Worker は処理担当、という役割分担を体で覚えることです 🌷 Cloudflare の React テンプレートは src/App.tsxworker/index.ts を分けたフルスタック構成になっていて、React から Worker を呼ぶのが基本形です。(Cloudflare Docs)


まずは全体像をつかもう 🗺️

この章の主役は、次の一本道です 😊

React画面 → fetch("/api/hello") → Worker → JSON → 画面更新

Cloudflare 公式の React + Vite ガイドでは、C3 で作ったプロジェクトに src/App.tsxworker/index.tswrangler.jsoncvite.config.ts が入り、worker/index.ts がバックエンド API として動きます。さらに Cloudflare Vite plugin は、Workers runtime と統合され、HMR を使ったローカル開発もしやすい設計です。(Cloudflare Docs)


なぜこのやり方が大事なの? 💡

React の画面から直接 Cloudflare の binding を触るのではなく、いったん Worker を通すのが Cloudflare らしい考え方です。公式ガイドでも、React アプリは binding に直接アクセスせず、Worker に fetch() して、その Worker が compute・storage・AI などの binding を使う流れが説明されています。つまり今日やる「画面 → API」の形は、あとで D1・KV・Workers AI につなぐときの土台そのものです。(Cloudflare Docs)


この章で作るミニ完成形 🌟

今回は、難しいことをいきなり増やしません。 まずは GET で 1 件の JSON を受け取る だけに絞ります。これで十分です 👍

Worker 側はこんな JSON を返します。

{
"message": "Cloudflare Workers API につながりました!",
"time": "2026-04-17T12:34:56.789Z"
}

React 側はそれを受け取って、画面に「つながった!」と表示します。 Cloudflare の公式チュートリアルでも、まずは /api/fetch("/api/") して JSON を返す最小構成から始めています。(Cloudflare Docs)

React to Worker Flow


Step 1. Worker 側に最初の API を作ろう 🛠️

まずは worker/index.ts をこんな感じにしてみましょう。

type HelloResponse = {
message: string;
time: string;
};

export default {
async fetch(request: Request) {
const url = new URL(request.url);

if (url.pathname === "/api/hello") {
const data: HelloResponse = {
message: "Cloudflare Workers API につながりました!",
time: new Date().toISOString(),
};

return Response.json(data);
}

return new Response("Not Found", { status: 404 });
},
} satisfies ExportedHandler;

ここで見てほしいのは 3 点です 😊

  1. new URL(request.url) で URL を読み取る
  2. url.pathname/api/hello かどうか判定する
  3. Response.json() で JSON を返す

Cloudflare の公式チュートリアルでも、fetch(request) の中で new URL(request.url) を作り、/api/ なら JSON を返し、それ以外は 404 を返す基本形が紹介されています。(Cloudflare Docs)

Worker Routing Logic


Step 2. React 側から fetch() してみよう 📡

次は src/App.tsx です。 まずは「ボタンを押したら API を呼ぶ」にします。最初の 1 本としては、これがいちばんわかりやすいです 🙌

import { useState } from "react";

type HelloResponse = {
message: string;
time: string;
};

export default function App() {
const [result, setResult] = useState<HelloResponse | null>(null);
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState("");

const loadHello = async () => {
try {
setLoading(true);
setErrorMessage("");

const res = await fetch("/api/hello");

if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}

const data = (await res.json()) as HelloResponse;
setResult(data);
} catch (error) {
console.error(error);
setErrorMessage("APIの呼び出しに失敗しました。");
} finally {
setLoading(false);
}
};

return (
<main style={{ padding: "24px", fontFamily: "sans-serif" }}>
<h1>第7章 API接続テスト 🔗</h1>

<button onClick={loadHello} disabled={loading}>
{loading ? "読み込み中..." : "Workers APIを呼ぶ"}
</button>

{errorMessage && <p style={{ color: "crimson" }}>⚠️ {errorMessage}</p>}

{result && (
<section style={{ marginTop: "16px" }}>
<p>{result.message}</p>
<p>🕒 {result.time}</p>
</section>
)}
</main>
);
}

Cloudflare の公式チュートリアルでも、React 側は fetch("/api/") のように相対パスで Worker を呼んでいます。つまり、この章では「別サーバーへ飛ぶ」意識よりも、「同じアプリの中の API を呼ぶ」感覚で大丈夫です。(Cloudflare Docs)


なぜ最初は useEffect ではなくボタンクリックなの? 👀

React 公式では、イベントハンドラは特定の操作が起きたときだけ動く、一方で Effect は依存値の変化に合わせて再同期する、と整理されています。さらに useEffect でデータ取得はできるものの、手動で書くとかなり“生っぽい”実装になりやすいとも説明されています。だから第7章では、まず 押したら呼ぶ というイベント駆動でつなぐのがいちばん理解しやすいです 😊(React)


Step 3. 画面に「通信の3状態」を作ろう 🎛️

API 接続では、最低でも次の 3 状態を持つとかなりアプリらしくなります ✨

  • まだ押していない
  • 読み込み中
  • 成功 または 失敗

この章では loadingerrorMessageresult の 3 つに分けました。 React 公式の useEffect 例でも、読み込み中に null を入れたり、後から結果をセットしたりして、通信状態を UI に反映する考え方が出てきます。第9章ではここをもっと丁寧に育てますが、第7章ではまず「通信には状態がある」とわかれば十分です。(React)

Fetch State Flow


Step 4. 開発サーバーで動かしてみよう 🚀

開発時は、これまでの章で作ったプロジェクトでそのまま npm run dev を使えば OK です。 Cloudflare の React ガイドでは、作成後に npm run dev でローカル開発サーバーを起動し、Vite の HMR と Cloudflare Vite plugin によって、Workers runtime に近い形で開発できます。Cloudflare の開発テスト資料でも、Vite plugin と Wrangler はどちらも Miniflare を土台にしていて、ローカルで Worker を実行できると説明されています。(Cloudflare Docs)


Step 5. wrangler.jsonc のルーティングを軽く理解しよう 🧭

React の SPA と Worker API を同じプロジェクトに置くと、 「このリクエストは画面用? API用?」という振り分けが必要になります。

Cloudflare の React テンプレートでは、assets.not_found_handlingsingle-page-application にして、React 側のルートを SPA として扱えるようにしています。公式チュートリアルでは、さらに必要なら run_worker_first: ["/api/*"] を入れて、/api/* を明示的に Worker へ流す形も紹介されています。(Cloudflare Docs)

こんな設定イメージです 👇

{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "my-react-app",
"compatibility_date": "2026-04-17",
"main": "./worker/index.ts",
"assets": {
"not_found_handling": "single-page-application",
"run_worker_first": ["/api/*"]
}
}

ブラウザの通常ナビゲーションでは Sec-Fetch-Mode: navigate が送られ、SPA 側の扱いになるのがデフォルトです。API ルートをはっきり Worker 優先にしたいときに run_worker_first が便利です。(Cloudflare Docs)

Wrangler Routing Config


ここで一度、頭を整理しよう 🧠✨

今やっていることを超シンプルに言うと、こうです。

  • React はボタンを押されたことを受け取る
  • fetch("/api/hello") で Worker にお願いする
  • Worker は JSON を返す
  • React は JSON を state に入れて表示する

この形にしておくと、あとで Worker 側だけを差し替えて、 ただのメッセージ API → 保存 API → AI API に進化させやすいです 🌈


よくあるつまずきポイント 😵‍💫

1. 404 になる /api/hello と Worker 側の url.pathname === "/api/hello" がずれていないか確認しましょう。

2. JSON ではなく HTML が返ってくる SPA 側に吸われている可能性があります。run_worker_first: ["/api/*"] の確認が有効です。公式チュートリアルでも、この明示設定が案内されています。(Cloudflare Docs)

3. res.json() で型が不安 TypeScript では、今回のように type HelloResponse = ... を先に作って、受け取る形を決めておくとかなり安心です 😊

4. 開発中に binding の挙動が本番と違う気がする Cloudflare の開発資料では、ローカル開発時は binding が基本的にローカルシミュレーションを使い、必要なら remote: true でリモート資源につなげられると説明されています。(Cloudflare Docs)


Copilot を使うなら、ここでこう使うと相性がいい 🤝✨

VS Code の GitHub Copilot は、エディタ全体を見ながら作業できる AI 支援として案内されていて、Chat は Windows なら Ctrl+Alt+I から開けます。さらに Chat では Agent Target から実行先を選べます。第7章のような「1ファイル追加」「fetch 関数を整える」「型を揃える」作業とかなり相性がいいです。(Visual Studio Code)

この章でのおすすめ依頼文は、たとえばこんな感じです 😊

App.tsx に /api/hello を呼ぶ fetch 関数を追加して。
loading / error / success の3状態を useState で整理して。
初心者向けで、複雑なカスタムフックは使わないで。

もう少し進んだら、こんなのも便利です。

worker/index.ts の /api/hello に Response.json を使った GET エンドポイントを追加して。
url.pathname で分岐し、他のパスは 404 を返して。

Cloudflare AI につなげるときも、流れは同じ 🤖☁️

ここ、すごく大事です。 Workers AI を使うときも、React から直接 AI をたたくのではなく、Worker を API 窓口にする、という考え方は同じです。Cloudflare の Workers AI ドキュメントでは、Worker から AI を使うには Wrangler かダッシュボードで AI binding を作る必要があると案内されています。React ガイドでも、React は binding に直接触らず Worker を通す構成です。(Cloudflare Docs)

たとえば将来は、Worker 側をこんなふうに変えられます ✨

type Env = {
AI: Ai;
};

export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);

if (url.pathname === "/api/summary") {
const result = await env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
prompt: "Cloudflare Workers を1文でやさしく説明して",
});

return Response.json(result);
}

return new Response("Not Found", { status: 404 });
},
} satisfies ExportedHandler<Env>;

Wrangler 側はこうです。

{
"ai": {
"binding": "AI"
}
}

Workers AI の公式資料では、env.AI.run(...) を使う例が示されています。また開発資料では、AI binding には現在ローカルシミュレーションがなく、AI は常にリモート実行で、remote: true を使う構成が推奨されています。(Cloudflare Docs)


この章で覚えてほしい「一番大事な一文」 🌈

React は見せる、Worker は受ける、binding は Worker の奥で使う。

この 1 本が見えたら、第7章はかなり成功です 🎉

Frontend and Backend Separation

Cloudflare の現在の公式導線も、React SPA と Worker API を組み合わせるフルスタック構成を中心にしていて、後続の binding・AI・保存機能へ自然につながるようになっています。(Cloudflare Docs)


章末まとめ 📝✨

この章では、React と Cloudflare Workers を実際に通信させる最初の 1 歩をやりました。

  • Worker 側で /api/hello を作る
  • React 側で fetch("/api/hello") する
  • JSON を state に入れて表示する
  • loadingerror を最低限持つ
  • /api/* を Worker 側へ流す考え方を知る
  • 将来の D1・KV・Workers AI も同じ入り口で広げられると知る

ここまでできると、次の章の POST とフォーム送信 がかなり入りやすくなります 📮✨


練習問題 🎓💪

  1. /api/hello の返り値に chapter: 7 を追加して、画面にも表示してみよう
  2. ボタン名を「通信テストする」に変えて、読み込み中は押せないようにしてみよう
  3. /api/time を新しく作って、現在時刻だけ返す API を増やしてみよう
  4. result がまだ無いときだけ「まだ通信していません」と表示してみよう
  5. Copilot に「App.tsx を初心者向けに整理して」と頼んで、差分を読んでみよう

必要なら次に、そのまま続きとして 「第7章の完成版教材として、もっと長い本文+図解風説明+章末課題つきの完全版」 に整えて出します。