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!
Prerequisites
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
- Next.js - we used
14.0.3
- TanStack React Query - we used
5.12.2
- Supabase SSR helpers - we used
0.0.10
- Supabase Cache Helpers - we used
@supabase-cache-helpers/postgrest-react-query
version1.3.0
- Supabase - create your account here if you do not have one
- IDE of your choosing
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:
_10npm 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.
Next, wrap the root in layout.tsx
:
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:
_11create table countries (_11 "id" serial primary key,_11 "name" text_11);_11_11insert into countries_11 (id, name)_11values_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:
_10supabase login_10supabase init_10supabase link_10supabase 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:
Creating a Browser Supabase Client
Creating a Server Supabase Client
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:
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:
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:
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:
Conclusion
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!