惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Security Archives - TechRepublic
Security Archives - TechRepublic
N
News and Events Feed by Topic
Last Week in AI
Last Week in AI
博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
O
OpenAI News
The Last Watchdog
The Last Watchdog
T
The Blog of Author Tim Ferriss
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
Forbes - Security
Forbes - Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
有赞技术团队
有赞技术团队
Jina AI
Jina AI
GbyAI
GbyAI
V
Vulnerabilities – Threatpost
L
LangChain Blog
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
AI
AI
博客园 - 聂微东
W
WeLiveSecurity
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Scott Helme
Scott Helme
罗磊的独立博客
Martin Fowler
Martin Fowler
S
Security Affairs
T
Tor Project blog
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
美团技术团队
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Security @ Cisco Blogs
T
Threat Research - Cisco Blogs
A
About on SuperTechFans
Cisco Talos Blog
Cisco Talos Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
I
Intezer
B
Blog
WordPress大学
WordPress大学
I
InfoQ
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
V2EX
P
Privacy & Cybersecurity Law Blog
雷峰网
雷峰网

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management
Using React Query with Next.js App Router and Supabase Cache Helpers
Giancarlo Buomprisco, Philipp Steinrötter, Thor Schaeff · 2024-01-12 · via Supabase Blog

Using React Query with Next.js App Router and Supabase Cache Helpers

TanStack Query, also known as React Query, is an open source state management library for React which handles caching, background updates and stale data out of the box with zero-configuration, which makes it an ideal tool to pair with supabase-js and our auto-generated REST API!

If you prefer video guides, we've got a three-part video series for you!

If you learn better by just jumping into a demo application, you can find one in our examples on GitHub.

Note: this blogpost is inspired by Giancarlo's original blogpost on using React Query with Supabase in Remix.io!

This article assumes that your have some basic kowledge of building React applications with Next.js. No prior knowledge of React Query or Supabase is required.

We will use the following tools

Install the required dependencies#

After you have created your Next.js project, e.g. with npx create-next-app@latest, you can install the required dependencies using the following command:


_10

npm install @supabase/supabase-js @tanstack/react-query @supabase/ssr @supabase-cache-helpers/postgrest-react-query


Creating a React Query client#

Create a React Query client in the root of your component tree. In Next.js app router applications, this is the layout.tsx file in the app folder.

The QueryClientProvider can only be used in client components and can't be directly embedded in the layout.tsx file. Therefore make sure to create a client component first, e.g.

components/ReactQueryClientProvider.tsx


_20

'use client'

_20

_20

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

_20

import { useState } from 'react'

_20

_20

export const ReactQueryClientProvider = ({ children }: { children: React.ReactNode }) => {

_20

const [queryClient] = useState(

_20

() =>

_20

new QueryClient({

_20

defaultOptions: {

_20

queries: {

_20

// With SSR, we usually want to set some default staleTime

_20

// above 0 to avoid refetching immediately on the client

_20

staleTime: 60 * 1000,

_20

},

_20

},

_20

})

_20

)

_20

return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>

_20

}


Next, wrap the root in layout.tsx:


_21

import type { Metadata } from 'next'

_21

import { Inter } from 'next/font/google'

_21

import './globals.css'

_21

import { ReactQueryClientProvider } from '@/components/ReactQueryClientProvider'

_21

_21

const inter = Inter({ subsets: ['latin'] })

_21

_21

export const metadata: Metadata = {

_21

title: 'Create Next App',

_21

description: 'Generated by create next app',

_21

}

_21

_21

export default function RootLayout({ children }: { children: React.ReactNode }) {

_21

return (

_21

<ReactQueryClientProvider>

_21

<html lang="en">

_21

<body className={inter.className}>{children}</body>

_21

</html>

_21

</ReactQueryClientProvider>

_21

)

_21

}


Creating your Database schema and generating TypeScript types#

For this example, we'll use a simple countries table where we store the id and name of countries. In your Supabase Dashboard SQL editor create the countries table and add some values:


_11

create table countries (

_11

"id" serial primary key,

_11

"name" text

_11

);

_11

_11

insert into countries

_11

(id, name)

_11

values

_11

(1, 'United Kingdom'),

_11

(2, 'United States'),

_11

(3, 'Singapore');


Once you've created your schema, you can use the Supabase CLI to automatically generate TypeScript types for you:


_10

supabase login

_10

supabase init

_10

supabase link

_10

supabase gen types typescript --linked --schema=public > utils/database.types.ts


These generated types will allow us to get typed data returned from React Query.

Creating supabase-js clients for client and server components#

To help you utilize the full power of supabase-js, including Supabase Auth and Row Level Security (RLS) policies, we provide the Supabase SSR helper library that allows you to conveniently create both browser Supabase clients for client components and server Supabase clients for server components.

Further reading: detailed documentation for Supabase SSR in Next.js

Create a TypedSupabaseClient type#

To make sure we have the proper typing available in all our components, we can create a TypedSupabaseClient type that we can hand to React Query:


_10

import { SupabaseClient } from '@supabase/supabase-js'

_10

import type { Database } from '@/utils/database.types'

_10

_10

export type TypedSupabaseClient = SupabaseClient<Database>


Creating a Browser Supabase Client#

utils/supabase-browser.ts


_25

import { createBrowserClient } from '@supabase/ssr'

_25

import type { Database } from '@/utils/database.types'

_25

import type { TypedSupabaseClient } from '@/utils/types'

_25

import { useMemo } from 'react'

_25

_25

let client: TypedSupabaseClient | undefined

_25

_25

function getSupabaseBrowserClient() {

_25

if (client) {

_25

return client

_25

}

_25

_25

client = createBrowserClient<Database>(

_25

process.env.NEXT_PUBLIC_SUPABASE_URL!,

_25

process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!

_25

)

_25

_25

return client

_25

}

_25

_25

function useSupabaseBrowser() {

_25

return useMemo(getSupabaseBrowserClient, [])

_25

}

_25

_25

export default useSupabaseBrowser


Creating a Server Supabase Client#


_17

import { createServerClient } from '@supabase/ssr'

_17

import { cookies } from 'next/headers'

_17

import { Database } from './database.types'

_17

_17

export default function useSupabaseServer(cookieStore: ReturnType<typeof cookies>) {

_17

return createServerClient<Database>(

_17

process.env.NEXT_PUBLIC_SUPABASE_URL!,

_17

process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,

_17

{

_17

cookies: {

_17

get(name: string) {

_17

return cookieStore.get(name)?.value

_17

},

_17

},

_17

}

_17

)

_17

}


Now we've got everything in place to get started fetching and caching data with React Query!

Automate query key management with the Supabase Cache Helpers#

React Query manages query caching based on query keys. Needing to manage query keys is somewhat burdensome, luckily this is where the Supabase Cache Helpers come into play.

Initially built during the Launch Week 5 Hackathon by Philipp Steinrötter, it has become a full blown open source project that automatically generates cache keys from your supabase-js queries, amongst many other awesome features!

Write reusable queries#

The most convenient way to use your queries across both server and client component is to define them in a central place, e.g. a queries folder:

queries/get-country-by-id.ts


_15

import { TypedSupabaseClient } from '@/utils/types'

_15

_15

export function getCountryById(client: TypedSupabaseClient, countryId: number) {

_15

return client

_15

.from('countries')

_15

.select(

_15

`

_15

id,

_15

name

_15

`

_15

)

_15

.eq('id', countryId)

_15

.throwOnError()

_15

.single()

_15

}


This is a simple query function that takes in either the browser or the server Supabase client and the id of a country, and returns a supabase-js query.

Fetch data server side#

In server components, we can now use this query with the prefetchQuery method:

app/ssrcountries/[id]/page.tsx


_22

import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'

_22

import { prefetchQuery } from '@supabase-cache-helpers/postgrest-react-query'

_22

import useSupabaseServer from '@/utils/supabase-server'

_22

import { cookies } from 'next/headers'

_22

import Country from '../country'

_22

import { getCountryById } from '@/queries/get-country-by-id'

_22

_22

export default async function CountryPage({ params }: { params: { id: number } }) {

_22

const queryClient = new QueryClient()

_22

const cookieStore = cookies()

_22

const supabase = useSupabaseServer(cookieStore)

_22

_22

await prefetchQuery(queryClient, getCountryById(supabase, params.id))

_22

_22

return (

_22

// Neat! Serialization is now as easy as passing props.

_22

// HydrationBoundary is a Client Component, so hydration will happen there.

_22

<HydrationBoundary state={dehydrate(queryClient)}>

_22

<Country id={params.id} />

_22

</HydrationBoundary>

_22

)

_22

}


Our query will be executed and fetch the data on the server. This means when using our query in the corresponding Country client component, the data will be immediately available upon render:

app/ssrcountries/country.tsx


_18

'use client'

_18

_18

import useSupabaseBrowser from '@/utils/supabase-browser'

_18

import { getCountryById } from '@/queries/get-country-by-id'

_18

import { useQuery } from '@supabase-cache-helpers/postgrest-react-query'

_18

_18

export default function Country({ id }: { id: number }) {

_18

const supabase = useSupabaseBrowser()

_18

// This useQuery could just as well happen in some deeper

_18

// child to <Posts>, data will be available immediately either way

_18

const { data: country } = useQuery(getCountryById(supabase, id))

_18

_18

return (

_18

<div>

_18

<h1>SSR: {country?.name}</h1>

_18

</div>

_18

)

_18

}


Since our query has them same generated cache key, React Query knows that the data was pre-fetched server side and therefore can render immediately without any loading state.

Fetch data client side#

Of course you can still combine this with fetching data client side. React Query will check if a given query was pre-fetched server side, but if it wasn't it will then go ahead and fetch the data client side side using the browser Supabase client:

app/countries/[id]/page.tsx


_24

'use client'

_24

_24

import useSupabaseBrowser from '@/utils/supabase-browser'

_24

import { getCountryById } from '@/queries/get-country-by-id'

_24

import { useQuery } from '@supabase-cache-helpers/postgrest-react-query'

_24

_24

export default function CountryPage({ params }: { params: { id: number } }) {

_24

const supabase = useSupabaseBrowser()

_24

const { data: country, isLoading, isError } = useQuery(getCountryById(supabase, params.id))

_24

_24

if (isLoading) {

_24

return <div>Loading...</div>

_24

}

_24

_24

if (isError || !country) {

_24

return <div>Error</div>

_24

}

_24

_24

return (

_24

<div>

_24

<h1>{country.name}</h1>

_24

</div>

_24

)

_24

}


React Query and the Supabase Cache Helpers are fantastic tools to help you manage data fetching and caching in your Next.js applications.

Using React Query with Server Components makes most sense if:

  • You have an app using React Query and want to migrate to Server Components without rewriting all the data fetching.
  • You want a familiar programming paradigm, but want to still sprinkle in the benefits of Server Components where it makes most sense.
  • You have some use case that React Query covers, but that your framework of choice does not cover.

It's hard to give general advice on when it makes sense to pair React Query with Server Components and not. If you are just starting out with a new Server Components app, we suggest you start out with any tools for data fetching your framework provides you with and avoid bringing in React Query until you actually need it. This might be never, and that's fine, as always: use the right tool for the job!