React Integration

Routier provides first-class support for React through the useQuery hook, enabling reactive data fetching with automatic updates when your data changes.

⚛️ Interactive React Demo

See Routier's React integration in action with live examples of `useQuery`, live queries, and reactive updates.

Open CodeSandbox Demo →

Features

  • Live Queries: Automatic re-renders when data changes
  • Type Safe: Full TypeScript support with discriminated unions
  • Performance Optimized: Built-in memoization and cleanup handling
  • Simple API: Minimal boilerplate, maximum productivity

Quick Start

import { useQuery } from "@routier/react";
import { useDataStore } from "./hooks/useDataStore";

function ProductsList() {
  const dataStore = useDataStore(); // Must be memoized in useDataStore hook

  const products = useQuery(
    (callback) => dataStore.products.subscribe().toArray(callback),
    [dataStore]
  );

  if (products.status === "pending") return <div>Loading...</div>;
  if (products.status === "error") return <div>Error!</div>;

  return (
    <ul>
      {products.status === "success" &&
        products.data.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
    </ul>
  );
}

Important: Your useDataStore hook must use useMemo to memoize the DataStore instance. Creating a new DataStore on every render will cause infinite subscription loops. See the Best Practices guide for details.

Installation

npm install @routier/react
# Install peer dependencies
npm install react react-dom

Core Concepts

useQuery Hook

The useQuery hook subscribes to Routier collections and returns loading, error, and success states:

const result = useQuery(
  (callback) => collection.subscribe().toArray(callback),
  [
    /* dependencies */
  ]
);

// result.status: 'pending' | 'success' | 'error'
// result.loading: boolean
// result.error: Error | null
// result.data: T | undefined

Automatic Updates

Queries automatically re-render when your data changes:

// Add a product
await dataStore.products.addAsync({ name: "New Product" });
await dataStore.saveChangesAsync();

// Component automatically re-renders with new data!

Type Safety

TypeScript knows exactly what state your component is in:

if (products.status === "success") {
  // TypeScript knows products.data is defined here
  console.log(products.data); // ✅ Safe
}

Concepts You’ll Need


Table of contents