Solid Query 是 TanStack Query 的官方 SolidJS 适配器,它能让你在 Web 应用中轻松实现数据获取、缓存、同步和更新服务端状态。
SolidJS 作为一个快速、响应式且声明式的用户界面构建库,正日益受到欢迎。它开箱即用地提供了许多功能。诸如 createSignal、createStore 等基础功能非常适合管理客户端状态。与其他 UI 库不同,SolidJS 对异步数据管理有着独到的见解。createResource API 是处理 SolidJS 应用中服务端状态的强大基础功能。resource 是一种特殊的信号 (signal),可在数据加载状态时触发 Suspense 边界。
import { createResource, ErrorBoundary, Suspense } from 'solid-js'
import { render } from 'solid-js/web'
function App() {
  const [repository] = createResource(async () => {
    const result = await fetch('https://api.github.com/repos/TanStack/query')
    if (!result.ok) throw new Error('Failed to fetch data')
    return result.json()
  })
  return (
    <div>
      <div>Static Content</div>
      {/* An error while fetching will be caught by the ErrorBoundary */}
      <ErrorBoundary fallback={<div>Something went wrong!</div>}>
        {/* Suspense will trigger a loading state while the data is being fetched */}
        <Suspense fallback={<div>Loading...</div>}>
          <div>{repository()?.updated_at}</div>
        </Suspense>
      </ErrorBoundary>
    </div>
  )
}
const root = document.getElementById('root')
render(() => <App />, root!)
import { createResource, ErrorBoundary, Suspense } from 'solid-js'
import { render } from 'solid-js/web'
function App() {
  const [repository] = createResource(async () => {
    const result = await fetch('https://api.github.com/repos/TanStack/query')
    if (!result.ok) throw new Error('Failed to fetch data')
    return result.json()
  })
  return (
    <div>
      <div>Static Content</div>
      {/* An error while fetching will be caught by the ErrorBoundary */}
      <ErrorBoundary fallback={<div>Something went wrong!</div>}>
        {/* Suspense will trigger a loading state while the data is being fetched */}
        <Suspense fallback={<div>Loading...</div>}>
          <div>{repository()?.updated_at}</div>
        </Suspense>
      </ErrorBoundary>
    </div>
  )
}
const root = document.getElementById('root')
render(() => <App />, root!)
这非常棒!只需几行代码,你就能从 API 获取数据并处理加载和错误状态。但随着应用复杂度的增长,你将需要更多功能来有效管理服务端状态。这是因为服务端状态与客户端状态完全不同。首先,服务端状态:
一旦理解了应用中服务端状态的本质,更多挑战将接踵而至,例如:
此时 Solid Query 应运而生。该库封装了 createResource,并提供了一系列钩子和工具来有效管理服务端状态。它开箱即用、零配置,并可根据应用增长按需定制。
从技术角度来看,Solid Query 能:
在下面的示例中,你可以看到 Solid Query 最基本、简单的用法,用于获取 TanStack Query GitHub 项目的统计信息:
import { ErrorBoundary, Suspense } from 'solid-js'
import {
  useQuery,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/solid-query'
function App() {
  const repositoryQuery = useQuery(() => ({
    queryKey: ['TanStack Query'],
    queryFn: async () => {
      const result = await fetch('https://api.github.com/repos/TanStack/query')
      if (!result.ok) throw new Error('Failed to fetch data')
      return result.json()
    },
    staleTime: 1000 * 60 * 5, // 5 minutes
    throwOnError: true, // Throw an error if the query fails
  }))
  return (
    <div>
      <div>Static Content</div>
      {/* An error while fetching will be caught by the ErrorBoundary */}
      <ErrorBoundary fallback={<div>Something went wrong!</div>}>
        {/* Suspense will trigger a loading state while the data is being fetched */}
        <Suspense fallback={<div>Loading...</div>}>
          {/* 
            The `data` property on a query is a SolidJS resource  
            so it will work with Suspense and transitions out of the box! 
          */}
          <div>{repositoryQuery.data?.updated_at}</div>
        </Suspense>
      </ErrorBoundary>
    </div>
  )
}
const root = document.getElementById('root')
const client = new QueryClient()
render(
  () => (
    <QueryClientProvider client={client}>
      <App />
    </QueryClientProvider>
  ),
  root!,
)
import { ErrorBoundary, Suspense } from 'solid-js'
import {
  useQuery,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/solid-query'
function App() {
  const repositoryQuery = useQuery(() => ({
    queryKey: ['TanStack Query'],
    queryFn: async () => {
      const result = await fetch('https://api.github.com/repos/TanStack/query')
      if (!result.ok) throw new Error('Failed to fetch data')
      return result.json()
    },
    staleTime: 1000 * 60 * 5, // 5 minutes
    throwOnError: true, // Throw an error if the query fails
  }))
  return (
    <div>
      <div>Static Content</div>
      {/* An error while fetching will be caught by the ErrorBoundary */}
      <ErrorBoundary fallback={<div>Something went wrong!</div>}>
        {/* Suspense will trigger a loading state while the data is being fetched */}
        <Suspense fallback={<div>Loading...</div>}>
          {/* 
            The `data` property on a query is a SolidJS resource  
            so it will work with Suspense and transitions out of the box! 
          */}
          <div>{repositoryQuery.data?.updated_at}</div>
        </Suspense>
      </ErrorBoundary>
    </div>
  )
}
const root = document.getElementById('root')
const client = new QueryClient()
render(
  () => (
    <QueryClientProvider client={client}>
      <App />
    </QueryClientProvider>
  ),
  root!,
)
确实如此!但正是这几行代码开启了一个全新的可能性世界。在上面的示例中,你的查询会被缓存 5 分钟,这意味着如果应用中任何地方在 5 分钟内挂载了使用相同查询的新组件,它将不会重新获取数据,而是使用缓存数据。这只是 Solid Query 开箱即用提供的众多功能之一。其他功能包括: