본문으로 건너뛰기

빠른 시작

TanStack DB는 API를 위한 반응형 로컬 우선 스토어입니다. 모든 뷰에 사용자 지정 엔드포인트를 만드는 작업을 중단하고 컴포넌트에 필요한 방식으로 데이터를 쿼리합니다. 이 예시에서는 다음 방법을 보여줍니다:

  • TanStack Query를 사용하여 컬렉션에 데이터 로드
  • 매우 빠른 라이브 쿼리로 데이터 쿼리
  • 즉각적인 낙관적 업데이트로 데이터 뮤테이션
import {
DbClient,
DbProvider,
collectionOptions,
eq,
useDbClient,
useLiveQuery,
} from '@tanstack/react-db'
import { QueryClient } from '@tanstack/query-core'
import { queryCollectionOptions } from '@tanstack/query-db-collection'

const queryClient = new QueryClient()
const dbClient = new DbClient({ queryClient })

// Define a stable collection descriptor that loads data using TanStack Query
const todoCollection = collectionOptions('todos', (client) =>
queryCollectionOptions({
id: 'todos',
queryKey: ['todos'],
queryClient: client.requireDependency<QueryClient>('queryClient'),
queryFn: async () => {
const response = await fetch('/api/todos')
return response.json()
},
getKey: (item) => item.id,
onUpdate: async ({ transaction }) => {
const { original, modified } = transaction.mutations[0]
await fetch(`/api/todos/${original.id}`, {
method: 'PUT',
body: JSON.stringify(modified),
})
},
})
)

function useTodoCollection() {
return useDbClient().collection(todoCollection)
}

function Todos() {
const todosCollection = useTodoCollection()

// Live query that updates automatically when data changes
const { data: todos } = useLiveQuery({
query: (q) =>
q.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.completed, false))
.orderBy(({ todo }) => todo.createdAt, 'desc'),
})

const toggleTodo = (todo) => {
// Instantly applies optimistic state, then syncs to server
todosCollection.update(todo.id, (draft) => {
draft.completed = !draft.completed
})
}

return (
<ul>
{todos.map((todo) => (
<li key={todo.id} onClick={() => toggleTodo(todo)}>
{todo.text}
</li>
))}
</ul>
)
}

function App() {
return (
<DbProvider client={dbClient}>
<Todos />
</DbProvider>
)
}

이제 컬렉션, 라이브 쿼리 및 낙관적 뮤테이션을 사용할 수 있습니다! 이를 더 자세히 살펴보겠습니다.

SSR로 구축하는 경우 이 빠른 시작 후에 SSR 및 Hydration 가이드를 참조할 수 있습니다. 간단히 말하면 SSR 앱은 안정적인 collectionOptions(...) 디스크립터를 사용하고, 서버에서 요청 범위의 DbClient를 통해 이를 구체화한 다음, React 훅이 DB에서 읽기 전에 명시적 컬렉션 행 또는 미리 로드된 라이브 쿼리 결과로 브라우저의 DbClient를 하이드레이션합니다.

설치​

npm install @tanstack/react-db @tanstack/query-db-collection @tanstack/query-core

1. 컬렉션 만들기​

컬렉션은 데이터를 저장하고 영속성을 처리합니다. queryCollectionOptions는 TanStack Query를 사용하여 데이터를 로드하고 서버 동기화를 위한 뮤테이션 핸들러를 정의합니다:

const todoCollection = collectionOptions('todos', (client) =>
queryCollectionOptions({
id: 'todos',
queryKey: ['todos'],
queryClient: client.requireDependency<QueryClient>('queryClient'),
queryFn: async () => {
const response = await fetch('/api/todos')
return response.json()
},
getKey: (item) => item.id,
// Handle all CRUD operations
onInsert: async ({ transaction }) => {
const { modified: newTodo } = transaction.mutations[0]
await fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
})
},
onUpdate: async ({ transaction }) => {
const { original, modified } = transaction.mutations[0]
await fetch(`/api/todos/${original.id}`, {
method: 'PUT',
body: JSON.stringify(modified),
})
},
onDelete: async ({ transaction }) => {
const { original } = transaction.mutations[0]
await fetch(`/api/todos/${original.id}`, { method: 'DELETE' })
},
})
)

위의 queryKey는 컬렉션을 로드하기 위한 TanStack Query의 캐시 키입니다. 아래의 React 라이브 쿼리는 구조화된 쿼리 IR에서 자체 식별자를 파생합니다.

2. 컬렉션 구체화​

컨텍스트의 DbClient를 사용하여 디스크립터를 구체화합니다. 작은 컬렉션 훅을 사용하면 컴포넌트에서 클라이언트 조회를 반복하지 않아도 됩니다:

function useTodoCollection() {
return useDbClient().collection(todoCollection)
}

3. 라이브 쿼리로 쿼리하기​

라이브 쿼리는 데이터가 변경되면 반응형으로 업데이트됩니다. 필터링, 정렬, 조인 및 변환을 지원합니다. React 훅은 기본적으로 구조화된 쿼리에서 쿼리 식별자를 파생하므로 일반 빌더 쿼리에는 별도의 queryKey가 필요하지 않습니다:

function TodoList() {
// Basic filtering and sorting
const { data: incompleteTodos } = useLiveQuery({
query: (q) =>
q.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.completed, false))
.orderBy(({ todo }) => todo.createdAt, 'desc'),
})

// Transform the data
const { data: todoSummary } = useLiveQuery({
query: (q) =>
q.from({ todo: todoCollection })
.select(({ todo }) => ({
id: todo.id,
summary: `${todo.text} (${todo.completed ? 'done' : 'pending'})`,
priority: todo.priority || 'normal'
})),
})

return <div>{/* Render todos */}</div>
}

4. 낙관적 뮤테이션​

뮤테이션은 즉시 적용되고 서버와 동기화됩니다. 서버 요청이 실패하면 변경 사항이 자동으로 롤백됩니다:

function TodoActions({ todo }) {
const todosCollection = useTodoCollection()

const addTodo = () => {
todosCollection.insert({
id: crypto.randomUUID(),
text: 'New todo',
completed: false,
createdAt: new Date(),
})
}

const toggleComplete = () => {
todosCollection.update(todo.id, (draft) => {
draft.completed = !draft.completed
})
}

const updateText = (newText) => {
todosCollection.update(todo.id, (draft) => {
draft.text = newText
})
}

const deleteTodo = () => {
todosCollection.delete(todo.id)
}

return (
<div>
<button onClick={addTodo}>Add Todo</button>
<button onClick={toggleComplete}>Toggle</button>
<button onClick={() => updateText('Updated!')}>Edit</button>
<button onClick={deleteTodo}>Delete</button>
</div>
)
}

다음 단계​

이제 TanStack DB의 기본 사항을 이해했습니다! 컬렉션은 데이터를 로드하고 영속화하며, 라이브 쿼리는 반응형 뷰를 제공하고, 뮤테이션은 자동 서버 동기화와 함께 즉각적인 피드백을 제공합니다.

다음 항목에 대한 자세한 내용은 문서에서 확인할 수 있습니다:

  • 설치 - 모든 프레임워크 및 컬렉션 패키지
  • 개요 - 전체 기능 개요 및 예시
  • 라이브 쿼리 - 고급 쿼리, 조인 및 집계