본문으로 건너뛰기

TanStack DB Solid 어댑터

설치

npm install @tanstack/solid-db

Solid 프리미티브

어댑터에서 사용할 수 있는 전체 프리미티브 목록은 Solid Functions Reference를 참조할 수 있습니다.

쿼리 작성(필터링, 조인, 집계 등)에 대한 종합적인 문서는 Live Queries Guide를 참조할 수 있습니다.

기본 사용법

useLiveQuery

useLiveQuery 프리미티브는 데이터가 변경될 때 컴포넌트를 자동으로 업데이트하는 라이브 쿼리를 생성합니다. 이 프리미티브는 data가 일반 배열이고 상태 필드(예: isLoading(), status())가 접근자인 객체를 반환합니다:

import { useLiveQuery } from '@tanstack/solid-db'
import { eq } from '@tanstack/db'
import { Show, For } from 'solid-js'

function TodoList() {
const query = useLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => eq(todos.completed, false))
.select(({ todos }) => ({ id: todos.id, text: todos.text }))
)

return (
<Show when={!query.isLoading()} fallback={<div>Loading...</div>}>
<ul>
<For each={query.data}>
{(todo) => <li>{todo.text}</li>}
</For>
</ul>
</Show>
)
}

참고: query.data는 함수가 아니라 배열을 직접 반환하지만, isLoading(), status() 등의 상태 필드는 접근자 함수입니다.

시그널을 사용한 반응형 쿼리

Solid는 세분화된 반응성을 사용하므로 쿼리가 시그널 변경을 자동으로 추적하고 이에 응답합니다. 쿼리 함수 내부에서 시그널을 호출하기만 하면 Solid가 시그널 변경 시 자동으로 다시 계산합니다:

import { createSignal } from 'solid-js'
import { useLiveQuery } from '@tanstack/solid-db'
import { gt } from '@tanstack/db'

function FilteredTodos(props: { minPriority: number }) {
const query = useLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => gt(todos.priority, props.minPriority))
)

return <div>{query.data.length} high-priority todos</div>
}

props.minPriority가 변경되면 Solid의 반응성 시스템이 자동으로 다음을 수행합니다:

  1. 쿼리 함수 내부의 prop 액세스를 감지합니다
  2. 이전 라이브 쿼리 컬렉션을 정리합니다
  3. 업데이트된 값을 사용하여 새 쿼리를 생성합니다
  4. 새 데이터로 컴포넌트를 업데이트합니다

컴포넌트 상태의 시그널 사용

import { createSignal } from 'solid-js'
import { useLiveQuery } from '@tanstack/solid-db'
import { eq, and } from '@tanstack/db'

function TodoList() {
const [userId, setUserId] = createSignal(1)
const [status, setStatus] = createSignal('active')

// Solid automatically tracks userId() and status() calls
const query = useLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => and(
eq(todos.userId, userId()),
eq(todos.status, status())
))
)

return (
<div>
<select onChange={(e) => setStatus(e.currentTarget.value)}>
<option value="active">Active</option>
<option value="completed">Completed</option>
</select>
<div>{query.data.length} todos</div>
</div>
)
}

핵심 사항: React와 달리 의존성 배열이 필요하지 않습니다. Solid의 반응형 시스템은 쿼리 실행 중 액세스된 모든 시그널, prop 또는 스토어를 자동으로 추적합니다.

모범 사례

쿼리 함수 내부에서 시그널에 액세스합니다:

import { createSignal } from 'solid-js'
import { useLiveQuery } from '@tanstack/solid-db'
import { gt } from '@tanstack/db'

function TodoList() {
const [minPriority, setMinPriority] = createSignal(5)

// Good - signal accessed inside query function
const query = useLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => gt(todos.priority, minPriority()))
)

// Solid automatically tracks minPriority() and recomputes when it changes
return <div>{query.data.length} todos</div>
}

쿼리 함수 외부에서 시그널을 읽면 안 됩니다:

import { createSignal } from 'solid-js'
import { useLiveQuery } from '@tanstack/solid-db'
import { gt } from '@tanstack/db'

function TodoList() {
const [minPriority, setMinPriority] = createSignal(5)

// Bad - reading signal outside query function
const currentPriority = minPriority()
const query = useLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => gt(todos.priority, currentPriority))
)
// Won't update when minPriority changes!

return <div>{query.data.length} todos</div>
}

정적 쿼리는 특별히 처리할 필요가 없습니다:

import { useLiveQuery } from '@tanstack/solid-db'

function AllTodos() {
// No signals accessed - query never changes
const query = useLiveQuery((q) =>
q.from({ todos: todosCollection })
)

return <div>{query.data.length} todos</div>
}

미리 생성된 컬렉션 사용

기존 컬렉션을 useLiveQuery에 전달할 수도 있습니다. 이는 여러 컴포넌트에서 쿼리를 공유할 때 유용합니다:

import { createLiveQueryCollection } from '@tanstack/db'
import { useLiveQuery } from '@tanstack/solid-db'

// Create collection outside component
const todosQuery = createLiveQueryCollection((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => eq(todos.active, true))
)

function TodoList() {
// Pass existing collection
const query = useLiveQuery(() => todosQuery)

return <div>{query.data.length} todos</div>
}