Token导航 LogoToken导航

Agent Skill · 研究检索

router-core%2fdata-loading(路由器核心%2f 数据加载)

用于辅助数据整理、表格处理、CSV/Excel 分析、指标计算和图表准备。它适合让 Agent 清洗字段、汇总数据、发现异常、生成统计口径或把分析结果转成可读说明。使用时需要确认数据来源、字段含义和时间范围,避免把样本数据当全量事实;涉及敏感数据、导出文件或批量写回时,应先确认权限和脱敏边界。

router-core%2fdata-loading 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证信息还不明确,暂无第三方扫描结果,按安装量在研究检索类的 73,675 个 Skill 里排第 43,251。

总安装 1,001周安装 43GitHub Stars 14,261下载 351核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:router-core%2fdata-loading(路由器核心%2f 数据加载)
来源仓库:https://github.com/tanstack/router
仓库路径:skills/router-core%2Fdata-loading
安装命令:
npx skills add https://github.com/tanstack/router --skill router-core/data-loading
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/tanstack/router --skill router-core/data-loading

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

router-core/data-loading 用于辅助数据整理、表格处理和指标计算,适合在 Codex、Claude、Cursor、Gemini CLI 中清洗字段或生成统计口径时使用。它适用于 CSV/Excel 分析和图表准备等数据处理场景。

通过 npx skills add 命令从指定 GitHub 仓库安装并使用该技能。使用时需确认数据来源和时间范围,避免将样本数据视为全量事实。router-core%2fdata-loading 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/router-core%2Fdata-loading

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/tanstack/router --skill router-core/data-loadi…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要操作浏览器,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

router-core%2fdata-loading 怎么安装?

在终端执行 npx skills add https://github.com/tanstack/router --skill router-core/data-loading。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

router-core%2fdata-loading 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

router-core%2fdata-loading 需要什么权限?

权限级别是操作浏览器。该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

router-core%2fdata-loading 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

router-core%2fdata-loading 用的人多吗?

公开数据是累计安装 1,001 次,近一周安装 43 次,下载 351 次,GitHub 14,261 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

router-core%2fdata-loading 安全吗?

没有查到第三方扫描结果,安全性无法从公开资料判断,安装前请自行审查源码、依赖和命令行为。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 来源仓库有 14,261 星,维护活跃度相对可查。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 没有第三方扫描结果,安全性只能靠自己读源码判断。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 要求有安全扫描结论才肯安装的团队。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
router-core%2fdata-loading

路由器核心%2f 数据加载 · 本页

1,00114,261操作浏览器未明确未收录

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Data Loading

Setup

Basic loader returning data, consumed via useLoaderData:

// src/routes/posts.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts')({
  loader: () => fetchPosts(),
  component: PostsComponent,
})

function PostsComponent() {
  const posts = Route.useLoaderData()
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

In code-split components, use getRouteApi instead of importing Route:

import { getRouteApi } from '@tanstack/react-router'

const routeApi = getRouteApi('/posts')

function PostsComponent() {
  const posts = routeApi.useLoaderData()
  return <ul>{/* ... */}</ul>
}

Route Loading Lifecycle

The router executes this sequence on every URL/history update:

  1. Route Matching (top-down)

- route.params.parse - route.validateSearch

  1. Route Pre-Loading (serial)

- route.beforeLoad - route.onError → route.errorComponent

  1. Route Loading (parallel)

- route.component.preload? - route.loader - route.pendingComponent (optional) - route.component - route.onError → route.errorComponent

Key: beforeLoad runs before loader. beforeLoad for a parent runs before its children's beforeLoad. Throwing in beforeLoad prevents all children from loading.

Core Patterns

loaderDeps for Search-Param-Driven Cache Keys

Loaders don't receive search params directly. Use loaderDeps to declare which search params affect the cache key:

// src/routes/posts.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts')({
  validateSearch: (search) => ({
    offset: Number(search.offset) || 0,
    limit: Number(search.limit) || 10,
  }),
  loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
  loader: ({ deps: { offset, limit } }) => fetchPosts({ offset, limit }),
})

When deps change, the route reloads regardless of staleTime.

SWR Caching Configuration

TanStack Router has built-in Stale-While-Revalidate caching keyed on the route's parsed pathname + loaderDeps.

Defaults:

  • staleTime: 0 — data is always considered stale, reloads in background on re-match
  • preloadStaleTime: 30 seconds — preloaded data won't be refetched for 30s
  • gcTime: 30 minutes — unused cache entries garbage collected after 30min
export const Route = createFileRoute('/posts')({
  loader: () => fetchPosts(),
  staleTime: 10_000, // 10s: data considered fresh for 10 seconds
  gcTime: 5 * 60 * 1000, // 5min: garbage collect after 5 minutes
})

Disable SWR caching entirely:

export const Route = createFileRoute('/posts')({
  loader: () => fetchPosts(),
  staleTime: Infinity,
})

Globally:

const router = createRouter({
  routeTree,
  defaultStaleTime: Infinity,
})

Pending States (pendingComponent / pendingMs / pendingMinMs)

By default, a pending component shows after 1 second (pendingMs: 1000) and stays for at least 500ms (pendingMinMs: 500) to avoid flash.

export const Route = createFileRoute('/posts')({
  loader: () => fetchPosts(),
  pendingMs: 500,
  pendingMinMs: 300,
  pendingComponent: () => <div>Loading posts...</div>,
  component: PostsComponent,
})

Router Context with createRootRouteWithContext (Factory Pattern)

createRootRouteWithContext is a factory that returns a function. You must call it twice — the first call passes the generic type, the second passes route options:

// src/routes/__root.tsx
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router'

interface MyRouterContext {
  auth: { userId: string }
  fetchPosts: () => Promise<Post[]>
}

// NOTE: double call — createRootRouteWithContext<Type>()({...})
export const Route = createRootRouteWithContext<MyRouterContext>()({
  component: () => <Outlet />,
})

Supply the context when creating the router:

// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

const router = createRouter({
  routeTree,
  context: {
    auth: { userId: '123' },
    fetchPosts,
  },
})

Consume in loaders and beforeLoad:

// src/routes/posts.tsx
export const Route = createFileRoute('/posts')({
  loader: ({ context: { fetchPosts } }) => fetchPosts(),
})

To pass React hook values into the router context, call the hook above RouterProvider and inject via the context prop:

import { RouterProvider } from '@tanstack/react-router'

function InnerApp() {
  const auth = useAuth()
  return <RouterProvider router={router} context={{ auth }} />
}

function App() {
  return (
    <AuthProvider>
      <InnerApp />
    </AuthProvider>
  )
}

Route-level context via beforeLoad:

export const Route = createFileRoute('/posts')({
  beforeLoad: () => ({
    fetchPosts: () => fetch('/api/posts').then((r) => r.json()),
  }),
  loader: ({ context: { fetchPosts } }) => fetchPosts(),
})

Deferred Data Loading

Return unawaited promises from the loader for non-critical data. Use the Await component to render them:

import { createFileRoute, Await } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
  loader: async ({ params: { postId } }) => {
    // Slow data — do NOT await
    const slowDataPromise = fetchComments(postId)
    // Fast data — await
    const post = await fetchPost(postId)

    return { post, deferredComments: slowDataPromise }
  },
  component: PostComponent,
})

function PostComponent() {
  const { post, deferredComments } = Route.useLoaderData()

  return (
    <div>
      <h1>{post.title}</h1>
      <Await
        promise={deferredComments}
        fallback={<div>Loading comments...</div>}
      >
        {(comments) => (
          <ul>
            {comments.map((c) => (
              <li key={c.id}>{c.body}</li>
            ))}
          </ul>
        )}
      </Await>
    </div>
  )
}

Invalidation After Mutations

router.invalidate() forces all active route loaders to re-run and marks all cached data as stale:

import { useRouter } from '@tanstack/react-router'

function AddPostButton() {
  const router = useRouter()

  const handleAdd = async () => {
    await fetch('/api/posts', { method: 'POST', body: '...' })
    router.invalidate()
  }

  return <button onClick={handleAdd}>Add Post</button>
}

For synchronous invalidation (wait until loaders finish):

await router.invalidate({ sync: true })

Error Handling

import {
  createFileRoute,
  ErrorComponent,
  useRouter,
} from '@tanstack/react-router'

export const Route = createFileRoute('/posts')({
  loader: () => fetchPosts(),
  errorComponent: ({ error, reset }) => {
    const router = useRouter()

    if (error instanceof CustomError) {
      return <div>{error.message}</div>
    }

    return (
      <div>
        <ErrorComponent error={error} />
        <button
          onClick={() => {
            // For loader errors, invalidate to re-run loader + reset boundary
            router.invalidate()
          }}
        >
          Retry
        </button>
      </div>
    )
  },
})

Loader Parameters

The loader function receives:

  • params — parsed path params
  • deps — object from loaderDeps
  • context — merged parent + beforeLoad context
  • abortController — cancelled when route unloads or becomes stale
  • cause — 'enter', 'stay', or 'preload'
  • preload — true during preloading
  • location — current location object
  • parentMatchPromise — promise of parent route match
  • route — the route object itself
export const Route = createFileRoute('/posts/$postId')({
  loader: ({ params: { postId }, abortController }) =>
    fetchPost(postId, { signal: abortController.signal }),
})

Common Mistakes

CRITICAL: Assuming loaders only run on the server

TanStack Router is client-first. Loaders run on the client by default. They also run on the server when using TanStack Start for SSR, but the default mental model is client-side execution.

// WRONG — this will crash in the browser
export const Route = createFileRoute('/posts')({
  loader: async () => {
    const fs = await import('fs') // Node.js only!
    return JSON.parse(fs.readFileSync('...')) // fails in browser
  },
})

// CORRECT — loaders run in the browser, use fetch or API calls
export const Route = createFileRoute('/posts')({
  loader: async () => {
    const res = await fetch('/api/posts')
    return res.json()
  },
})

Do NOT put database queries, filesystem access, or server-only code in loaders unless you are using TanStack Start server functions.

MEDIUM: Not understanding staleTime default is 0

Default staleTime is 0. This means data reloads in the background on every route re-match. This is intentional — it ensures fresh data. But if your data is expensive or static, set staleTime:

export const Route = createFileRoute('/posts')({
  loader: () => fetchPosts(),
  staleTime: 60_000, // Consider fresh for 1 minute
})

HIGH: Using reset() instead of router.invalidate() in error components

reset() only resets the error boundary UI. It does NOT re-run the loader. For loader errors, use router.invalidate() which re-runs loaders and resets the boundary:

// WRONG — resets boundary but loader still has stale error
function PostErrorComponent({ error, reset }) {
  return <button onClick={reset}>Retry</button>
}

// CORRECT — re-runs loader and resets the error boundary
function PostErrorComponent({ error }) {
  const router = useRouter()
  return <button onClick={() => router.invalidate()}>Retry</button>
}

HIGH: Missing double parentheses on createRootRouteWithContext

createRootRouteWithContext<Type>() is a factory — it returns a function. Must call twice:

// WRONG — missing second call, passes options to the factory
const rootRoute = createRootRouteWithContext<{ auth: AuthState }>({
  component: RootComponent,
})

// CORRECT — factory()({options})
const rootRoute = createRootRouteWithContext<{ auth: AuthState }>()({
  component: RootComponent,
})

HIGH: Using React hooks in beforeLoad or loader

beforeLoad and loader are NOT React components. You cannot call hooks inside them. Use router context to inject values from hooks:

// WRONG — hooks cannot be called outside React components
export const Route = createFileRoute('/posts')({
  loader: () => {
    const auth = useAuth() // This will crash!
    return fetchPosts(auth.userId)
  },
})

// CORRECT — inject hook values via router context
// In your App component:
function InnerApp() {
  const auth = useAuth()
  return <RouterProvider router={router} context={{ auth }} />
}

// In your route:
export const Route = createFileRoute('/posts')({
  loader: ({ context: { auth } }) => fetchPosts(auth.userId),
})

HIGH: Property order affects TypeScript inference

Router infers types from earlier properties into later ones. Declaring beforeLoad after loader means context from beforeLoad is unknown in the loader:

// WRONG — context.user is unknown because beforeLoad declared after loader
export const Route = createFileRoute('/admin')({
  loader: ({ context }) => fetchData(context.user),
  beforeLoad: () => ({ user: getUser() }),
})

// CORRECT — validateSearch → loaderDeps → beforeLoad → loader
export const Route = createFileRoute('/admin')({
  beforeLoad: () => ({ user: getUser() }),
  loader: ({ context }) => fetchData(context.user),
})

HIGH: Returning entire search object from loaderDeps

// WRONG — loader re-runs on ANY search param change
loaderDeps: ({ search }) => search

// CORRECT — only re-run when page changes
loaderDeps: ({ search }) => ({ page: search.page })

Returning the whole search object means unrelated param changes (e.g., sortDirection, viewMode) trigger unnecessary reloads because deep equality fails on the entire object.

Tensions

  • Client-first loaders vs SSR expectations: Loaders run on the client by default. When using SSR (TanStack Start), they run on both client and server. Browser-only APIs work by default but break under SSR. Server-only APIs (fs, db) break by default but work under Start server functions. See router-core/ssr/SKILL.md.
  • Built-in SWR cache vs external cache coordination: Router has built-in caching. When using TanStack Query, set defaultPreloadStaleTime: 0 to avoid double-caching. See compositions/router-query/SKILL.md.

Cross-References

  • See also: router-core/search-params/SKILL.md — loaderDeps consumes validated search params as cache keys
  • See also: compositions/router-query/SKILL.md — for external cache coordination with TanStack Query

平台分布

Codex

36.16%
按下载量换算127

Claude

30.08%
按下载量换算106

Cursor

16.75%
按下载量换算59

Gemini CLI

9.02%
按下载量换算32

安全审计

暂无安全审计结果可展示。

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills