data

GitHub

规范 Next.js 数据获取模式,定义服务端页面预取、客户端组件接收初始数据及 SWR Hook 缓存更新的核心流程。提供 API 客户端使用指南,明确服务器与客户端组件的职责划分,并规定状态管理需遵循 React 标准而非 nuqs。

.agents/skills/data/SKILL.md trycompai/comp

Trigger Scenarios

实现数据获取逻辑 调用 API 接口 开发服务端或客户端组件 编写 SWR 数据钩子

Install

npx skills add trycompai/comp --skill data -g -y
More Options

Non-standard path

npx skills add https://github.com/trycompai/comp/tree/main/.agents/skills/data -g -y

Use without installing

npx skills use trycompai/comp@data

指定 Agent (Claude Code)

npx skills add trycompai/comp --skill data -a claude-code -g -y

安装 repo 全部 skill

npx skills add trycompai/comp --all -g -y

预览 repo 内 skill

npx skills add trycompai/comp --list

SKILL.md

Frontmatter
{
    "name": "data",
    "description": "Use when implementing data fetching, API calls, server\/client components, or SWR hooks"
}

Source Cursor rule: .cursor/rules/data.mdc. Original Cursor alwaysApply: false.

Data Fetching

Core Pattern: Server → Client → SWR

1. Server Page Fetches Data

// app/(app)/[orgId]/tasks/page.tsx
export default async function TasksPage({ params }: { params: Promise<{ orgId: string }> }) {
  const { orgId } = await params; // From URL, NOT session
  const tasks = await getTasks(orgId);
  return <TaskListClient organizationId={orgId} initialTasks={tasks} />;
}

2. Client Component Receives Initial Data

// components/TaskListClient.tsx
'use client';

export function TaskListClient({ organizationId, initialTasks }: Props) {
  const { tasks, createTask, updateTask } = useTasks({
    organizationId,
    initialData: initialTasks,
  });
  // Initial render is instant - no loading state
}

3. SWR Hook with fallbackData

// hooks/useTasks.ts
export function useTasks({ organizationId, initialData }: UseTasksOptions) {
  const { data, mutate } = useSWR(
    ['/v1/tasks', organizationId], // Include orgId for cache isolation
    async ([endpoint, orgId]) => {
      const response = await apiClient.get(endpoint, orgId);
      return response.data?.tasks ?? [];
    },
    { fallbackData: initialData }
  );

  const createTask = async (input: CreateTaskInput) => {
    await apiClient.post('/v1/tasks', input, organizationId);
    mutate(); // Revalidate
  };

  const updateTask = async ({ taskId, input }: { taskId: string; input: UpdateTaskInput }) => {
    await apiClient.put(`/v1/tasks/${taskId}`, input, organizationId);
    mutate(); // Revalidate
  };

  return { tasks: data ?? [], createTask, updateTask, mutate };
}

API Client

Use apiClient from @/lib/api-client:

import { apiClient } from '@/lib/api-client';

await apiClient.get<ResponseType>('/v1/endpoint', organizationId);
await apiClient.post<ResponseType>('/v1/endpoint', body, organizationId);
await apiClient.put<ResponseType>('/v1/endpoint', body, organizationId);
await apiClient.delete('/v1/endpoint', organizationId);

Server vs Client Components

Layouts = server. Interactive logic in separate client components.

// layout.tsx (server)
export default function Layout({ children }) {
  return (
    <PageLayout>
      <PageHeader title="Title" />
      <ClientTabs /> {/* Client component */}
      {children}
    </PageLayout>
  );
}

// components/ClientTabs.tsx
'use client';
export function ClientTabs() {
  const router = useRouter();
  // Interactive logic here
}

State Management

No nuqs - use React state or Next.js patterns:

// ✅ React state for UI
const [isOpen, setIsOpen] = useState(false);

// ✅ Next.js for URL state
const router = useRouter();
const searchParams = useSearchParams();

// ❌ No nuqs
import { useQueryState } from 'nuqs';

Rules

// ✅ Always
const { orgId } = await params;                    // From URL params
const { data } = useSWR(key, f, { fallbackData }); // With initial data
await apiClient.get('/v1/endpoint', orgId);        // Use apiClient
useSWR(['/v1/tasks', orgId], fetcher);            // Include orgId in key

// ❌ Never
const orgId = session?.activeOrganizationId;       // From session
const { data } = useSWR('/api/data');              // No initial data
await fetch('/api/endpoint');                      // Direct fetch

File Structure

app/(app)/[orgId]/tasks/
├── page.tsx                 # Server - fetches data
├── components/
│   └── TaskListClient.tsx   # Client - receives initialData
├── hooks/
│   └── useTasks.ts          # SWR hook with mutations
└── data/
    └── queries.ts           # Server-side queries

Version History

  • 0ccfcc2 Current 2026-09-27 10:22

Same Skill Collection

.agents/skills/audit-design-system/SKILL.md
.agents/skills/audit-hooks/SKILL.md
.agents/skills/audit-rbac/SKILL.md
.agents/skills/audit-tests/SKILL.md
.agents/skills/better-auth-best-practices/SKILL.md
.agents/skills/billing/SKILL.md
.agents/skills/code/SKILL.md
.agents/skills/cursor-usage/SKILL.md
.agents/skills/diagnose-generation-failure/SKILL.md
.agents/skills/forms/SKILL.md
.agents/skills/generate-mcp-server/SKILL.md
.agents/skills/infra/SKILL.md
.agents/skills/manage-openapi-overlays/SKILL.md
.agents/skills/new-feature-setup/SKILL.md
.agents/skills/production-readiness/SKILL.md
.agents/skills/prompt-engineering/SKILL.md
.agents/skills/speakeasy-context/SKILL.md
.agents/skills/stale-worktree-cleanup/SKILL.md
.agents/skills/trigger-advanced-tasks/SKILL.md
.agents/skills/trigger-basic/SKILL.md
.agents/skills/trigger-config/SKILL.md
.agents/skills/trigger-realtime/SKILL.md
.agents/skills/ui/SKILL.md
.claude/skills/api-endpoint-contract/SKILL.md
.claude/skills/audit-design-system/SKILL.md
.claude/skills/audit-hooks/SKILL.md
.claude/skills/audit-rbac/SKILL.md
.claude/skills/audit-tests/SKILL.md
.claude/skills/check-results-service/SKILL.md
.claude/skills/cleanup/SKILL.md
.claude/skills/code/SKILL.md
.claude/skills/cursor-usage/SKILL.md
.claude/skills/data/SKILL.md
.claude/skills/forms/SKILL.md
.claude/skills/infra/SKILL.md
.claude/skills/new-feature-setup/SKILL.md
.claude/skills/production-readiness/SKILL.md
.claude/skills/prompt-engineering/SKILL.md
.claude/skills/security-review/SKILL.md
.claude/skills/stale-worktree-cleanup/SKILL.md
.claude/skills/trigger-advanced-tasks/SKILL.md
.claude/skills/trigger-basic/SKILL.md
.claude/skills/trigger-config/SKILL.md
.claude/skills/trigger-realtime/SKILL.md
.claude/skills/ui/SKILL.md
.agents/skills/essentials/SKILL.md
.agents/skills/prisma/SKILL.md
.agents/skills/trigger-scheduled-tasks/SKILL.md
.claude/skills/essentials/SKILL.md

Metadata

Files
0
Version
0ccfcc2
Hash
65aa1d40
Indexed
2026-09-27 10:22

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-27 23:55
浙ICP备14020137号-1