Dữ liệu & route handler
Phục vụ bản triển khai từ app/api, lấy chúng trong trang và gửi bản mới.
Trong chương này
- Một route handler
- Lấy dữ liệu trong trang
- Trạng thái tải và lỗi
- Truyền dữ liệu theo luồng
Acme Deploys cần dữ liệu thực. Route handler nằm cạnh các trang trong app/, dùng API Web Request và Response, và chạy trên text dev và text start. Chúng dùng chung origin với ứng dụng nên các yêu cầu không cần cấu hình CORS.
Một route handler
Đã thêm: import { DEPLOYMENTS, createDeployment } from "../../../lib/deployments";Đã thêm: Đã thêm: export function GET(): Response {Đã thêm: return Response.json(DEPLOYMENTS);Đã thêm: }Đã thêm: Đã thêm: export async function POST(req: Request): Promise<Response> {Đã thêm: const deployment = createDeployment(await req.json());Đã thêm: return Response.json(deployment, { status: 201 });Đã thêm: }Gọi route handler từ prompt của console khi text dev đang chạy:
await (await fetch("/api/deployments")).json()Lấy dữ liệu trong trang
Lấy dữ liệu trong một effect và hiển thị <Spinner> cho đến khi có dữ liệu. r lấy lại dữ liệu; n gửi yêu cầu tạo bản triển khai mới, bản này xuất hiện với trạng thái đang dựng và chuyển sang sẵn sàng khi quá trình dựng hoàn tất.
Đã xóa: import { DEPLOYMENTS } from "../../lib/deployments";Đã thêm: import { useEffect, useState } from "react";Đã thêm: import { Spinner, useInput } from "@textjs/app";Đã thêm: import type { Deployment } from "../../lib/deployments";export default function DeploymentsPage() {Đã thêm: const [rows, setRows] = useState<Deployment[]>([]);Đã thêm: const [loading, setLoading] = useState(true);Đã thêm: Đã thêm: const refetch = async () => {Đã thêm: setLoading(true);Đã thêm: setRows(await (await fetch("/api/deployments")).json());Đã thêm: setLoading(false);Đã thêm: };Đã thêm: useEffect(() => void refetch(), []);Đã thêm: Đã thêm: useInput((e) => {Đã thêm: if (e.input === "r") void refetch();Đã thêm: if (e.input === "n") void fetch("/api/deployments", { method: "POST", body: "{}" }).then(refetch);Đã thêm: });Đã thêm: Đã thêm: if (loading) return <Spinner label="Loading deployments…" />; return ( <Box className="flex-col">Đã xóa: {DEPLOYMENTS.map((d) => (Đã thêm: {rows.map((d) => ( <Box key={d.id} className="flex-row h-1 gap-2">Đã thêm: <Status status={d.status} /> …Trạng thái tải và lỗi
Thay vì xử lý loading thủ công, loading.tsx nằm cạnh trang sẽ hiển thị khi trang tạm dừng, còn error.tsx bắt mọi lỗi trang ném ra. Cả hai đều là component thông thường:
import { Spinner } from "@textjs/app";export default function Loading() { return <Spinner label="Loading deployments…" />;}Truyền dữ liệu theo luồng
Handler có thể trả về một ReadableStream, qua đó nhật ký dựng truyền vào bảng tổng quan từng dòng. Xem Route handler để biết về sự kiện do máy chủ gửi và chuyển tiếp qua proxy đến một daemon cục bộ.
Dùng thử
Đây là Acme Deploys ở cuối chương, đang chạy trong DevTools. Nhấp vào vùng focus, rồi dùng các phím bên dưới.
Mở console
Ứng dụng render trong DevTools.Trước tiên bật “Hiển thị tính năng cho nhà phát triển web” trong Cài đặt Safari → Nâng cao. Sau đó nhấp vào đây và nhấn r.
Mở trên máy tính
Ứng dụng này render trong console của DevTools, cần trình duyệt trên máy tính.
Bài trắc nghiệm
2 câu hỏiTrả lời mọi câu hỏi để hoàn thành chương.