This demo showcases the integration of TanStack Table with ElectricSQL, demonstrating both problematic (infinite loop) and correct implementations when using reactive data queries.
- Node.js 18+ and pnpm
- A Supabase account (free tier works)
- An ElectricSQL Cloud account (free tier works)
pnpm install- Go to Supabase and create a new project (free tier)
- Once created, go to your project settings
- Navigate to Settings → Database
- Copy the Connection string (URI) - you'll need the "Transaction" mode URL
- Make note of your database password
- Go to ElectricSQL Cloud and sign up (free)
- Create a new app with the supabase database as the source
- In your app dashboard, find your:
- Source ID (looks like:
2559f49f-62fc-4986-b7c0-cfb683b4c5bc) - Source Secret (a JWT token)
- Source ID (looks like:
- Keep these handy for the next step
Create a .env file in the project root:
# Supabase Database URL (from step 2.4)
DATABASE_URL=postgresql://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-0-[REGION].pooler.supabase.com:6543/postgres
# ElectricSQL Cloud (from step 3.3)
ELECTRIC_URL=https://api.electric-sql.cloud
ELECTRIC_SOURCE_ID=your-source-id-here
ELECTRIC_SOURCE_SECRET=your-source-secret-jwt-herepnpm db:generateThis will generate the database schema based on the Drizzle configuration.
pnpm db:migrateThis creates the todos table in your Supabase database.
In one terminal, start the ElectricSQL proxy server:
pnpm tsx ./server.tsThe server will start on http://localhost:3000 and proxy ElectricSQL requests with authentication.
In another terminal, start the Vite development server:
pnpm run devOpen http://localhost:5173 in your browser.
To see the demo in action, you can add some todos through the Supabase UI:
- Go to your Supabase project dashboard
- Navigate to Table Editor in the left sidebar
- Select the
todostable - Click Insert → Insert row
- Add a few sample todos with:
title: Any text like "Buy groceries" or "Write documentation"completed: Toggle true/false- Leave
idandcreatedAtempty (they'll be auto-generated)
- Click Save to add the todo
The todos will automatically sync to your app through ElectricSQL!
The demo includes a switcher between two implementations:
- Todo Inline (problematic) - Demonstrates the infinite loop issue when using
useLiveQuerydirectly with TanStack Table - Todo Wrapper (solution) - Shows the correct pattern using a wrapper component to handle data fetching
When using useLiveQuery directly in a component that also uses TanStack Table, the reactive query creates new references on each render, causing infinite re-renders.
Separate data fetching concerns by:
- Creating a wrapper component that handles the
useLiveQuery - Passing stable data props to the table component
- Keeping TanStack Table isolated from reactive data sources
src/
├── todo-inline/
│ └── TodoTable.tsx # Problematic implementation (infinite loops)
├── todo-wrapper/
│ ├── TodoTable.tsx # Clean table component
│ └── TodoTableWrapper.tsx # Data fetching wrapper
├── electric.config.ts # ElectricSQL configuration
├── todo.collection.ts # TanStack DB collection setup
└── App.tsx # Main app with implementation switcher
server.ts # ElectricSQL proxy server
- Check server console for detailed error logs
- Verify your
ELECTRIC_SOURCE_IDandELECTRIC_SOURCE_SECRETare correct - Ensure your Supabase database is accessible
- Make sure the proxy server is running on port 3000
- Check that the Vite dev server is on port 5173
- Verify the
todostable exists in Supabase - Check ElectricSQL Cloud console for sync status
- Ensure migrations ran successfully