Why I don't use React-Query and tRPC anymore
Summary
TLDRThis video provides an in-depth analysis of using React Query and tRPC in Next.js applications. The creator explains why they no longer use these tools in Next.js, despite acknowledging their usefulness outside of it. The video highlights Next.js's built-in caching capabilities, server components, and server actions, which offer similar benefits to React Query and tRPC while streamlining the development process. It also discusses the trade-offs between these approaches, giving developers a comprehensive understanding of when to use React Query, tRPC, or Next.js's native features. Overall, the video serves as a valuable resource for developers seeking to optimize their Next.js applications.
Takeaways
- 👍 The author no longer uses React Query or tRPC in Next.js applications, preferring the built-in caching and server-side rendering capabilities of Next.js.
- 💻 In traditional React apps, React Query is useful for caching and avoiding redundant network requests, but Next.js handles this automatically.
- 🔄 Next.js aggressively caches data fetched on the server, even persisting through deployments, making React Query unnecessary for server-side data fetching.
- ⚡ Next.js also caches the rendered output (RSC payload) and has a client-side cache, contributing to its snappy performance.
- 🔗 The Next.js Link component prefetches pages as they come into the viewport, further enhancing performance.
- 💼 While React Query may still be useful for client-side fetching in specific cases like infinite scrolling or polling, it's generally not needed in Next.js.
- 🔐 For type-safe client-server communication in traditional React apps, tRPC is helpful, but in Next.js, server components and server actions provide similar type safety without the need for tRPC.
- ✍️ Server actions in Next.js are similar to local functions, with TypeScript inferring the return types, providing type safety for server-side mutations.
- 📂 The author prefers separating server actions into dedicated files, treating them as important functions in the codebase.
- 🌐 If supporting clients outside Next.js (e.g., React Native) is a requirement, tRPC may still be necessary, as server actions cannot be used outside Next.js.
Q & A
Why did the speaker stop using React Query and tRPC in the latest Next.js?
-The speaker stopped using React Query in Next.js because Next.js comes with built-in caching mechanisms that automatically cache fetch requests and render results. Therefore, React Query's main purpose of caching data is already handled by Next.js. As for tRPC, Next.js introduced server actions, which provide a similar type-safe way of handling client-server communication without the need for tRPC.
How does Next.js handle data fetching and caching?
-Next.js has three main caching mechanisms: 1) It caches the result of individual fetch calls, 2) It caches the render result of server components (RSC payload), and 3) It uses a client-side cache. Additionally, Next.js automatically prefetches data for links when they come into the viewport.
What are the benefits of using server actions in Next.js instead of tRPC?
-Server actions in Next.js provide type-safety, intelligent code suggestions, and automatic type inference for return values, similar to tRPC. However, server actions are integrated with Next.js and do not require additional boilerplate. They also offer progressive enhancement and integration with powerful hooks like useFormStatus and useOptimistic.
How do server actions handle client-side validation?
-Since server actions cannot trust data coming from the client, they need to validate the input data. This can be done using a library like Zod, similar to how validation is handled in tRPC. After validation, the data is properly typed and can be used safely.
What is the potential downside of using server actions in Next.js?
-One downside of server actions is that they cannot be easily used outside of Next.js. If the plan is to support clients outside of Next.js, such as a React Native mobile app, tRPC may be a better choice for handling client-server communication.
How does the speaker recommend handling client-side data fetching in Next.js?
-For client-side data fetching in Next.js, such as in cases like infinite scrolling or polling, the speaker still recommends using React Query since the fetch API is not automatically cached by Next.js.
What is the role of the Suspense component in Next.js when it comes to data fetching?
-In Next.js, the Suspense component is used to wrap the page component that fetches data. The fallback prop of Suspense is used to render a loading spinner while the data is being fetched asynchronously.
How does Next.js handle prefetching data for links?
-Next.js automatically prefetches data for links that come into the viewport when using the Link component. However, this prefetching behavior is only enabled in production mode.
What is the speaker's recommendation for mastering the latest React and Next.js?
-The speaker highly recommends going through their professional React and Next.js course, which starts from scratch and covers building cutting-edge Next.js applications by the end.
When would the speaker still consider using React Query and tRPC?
-The speaker would still use React Query and tRPC in a React Feat app or a Create React App, as the caching and type-safety benefits provided by these libraries are still relevant in those environments.
Outlines
🔍 Comparing React Query and Next.js for Data Fetching
The video starts by explaining why the speaker no longer uses React Query or tRPC in Next.js applications, even though they are useful tools outside Next.js. Using a React project example, the speaker demonstrates how React Query caches data fetching requests, eliminating unnecessary network requests for previously fetched data. However, in Next.js, the built-in caching mechanisms automatically handle this, making React Query unnecessary for data fetching in Next.js apps.
⚡ Next.js Built-in Caching and React Server Components
The speaker explains how Next.js has three main caching mechanisms: caching individual fetch calls, caching the render result (React Server Component payload), and a client-side cache. These caching mechanisms, along with the Suspense component for handling loading states and the Link component for prefetching, make Next.js applications highly performant. The speaker demonstrates how clicking through different job items in a Next.js app does not trigger new network requests due to the aggressive caching.
🔐 Type Safety with tRPC vs. Next.js Server Actions
The video compares the benefits of using tRPC for type-safe client-server communication with the newer Next.js Server Actions feature. While tRPC provides type safety and autocompletion for API endpoints, Next.js Server Actions achieve similar benefits by leveraging TypeScript's inference capabilities. The speaker demonstrates how Server Actions provide type safety for both input and output data, without the need for additional boilerplate. However, one downside of Server Actions is the potential loss of autocomplete when using the more precise 'unknown' type for input validation.
🛠 Implementing Server Actions in Next.js
The speaker dives into the implementation details of Server Actions in Next.js. Server Actions are defined as functions within a 'server' module, enabling type-safe input validation and handling of mutations on the server side. The video showcases how Server Actions integrate with features like form handling, progressive enhancement, and optimistic UI updates. The speaker also discusses potential workarounds for the autocomplete issue and considerations for supporting clients outside Next.js, where tRPC might be a better choice.
Mindmap
Keywords
💡React Query
💡tRPC
💡Next.js
💡Caching
💡Data Fetching
💡useEffect
💡Server Components
💡Type Safety
💡Server Actions
💡Prisma
Highlights
The speaker explains why they no longer use React Query or tRPC in Next.js applications, as Next.js provides built-in caching and server components that offer similar benefits without the need for these libraries.
In a React application (without Next.js), the speaker would still use React Query for data fetching and caching to avoid unnecessary network requests.
Next.js automatically caches the result of fetch calls, the render result (RSC payload), and has a client-side cache, making it very performant and reducing the need for libraries like React Query.
The speaker demonstrates how Next.js automatically caches fetched data and shows no new network requests for already fetched data, unlike traditional React applications.
With traditional React applications, every click on an item triggers a new network request, as there is no built-in caching mechanism.
In Next.js, the speaker uses the built-in Suspense component with a fallback to show a loading spinner while data is being fetched.
The speaker explains how Next.js also prefetches data for links in the viewport, further improving performance.
For client-side fetching or polling in Next.js, the speaker acknowledges the potential need for React Query, as the built-in caching is for server-side fetching.
The speaker highlights the benefits of tRPC in traditional React applications, including type safety, automatic endpoint handling, and intelligent code suggestions.
In Next.js, the speaker uses server components and an ORM (Prisma) to achieve type safety and avoid remembering API endpoints, similar to the benefits of tRPC.
For mutations (POST, PUT, DELETE) in traditional React applications, the speaker explains the lack of type safety and endpoint intelligence without tRPC.
Next.js introduces Server Actions, which provide type safety, endpoint intelligence, and progressive enhancement for mutations, similar to tRPC.
The speaker demonstrates how Server Actions provide intelligent code suggestions, type safety, and automatic endpoint handling, similar to tRPC.
Server Actions have some downsides, such as losing type safety when using the precise 'unknown' type for input validation and limited usage outside Next.js applications.
The speaker recommends using their professional React and Next.js course to master the latest developments in the field.
Transcripts
everyone I've been getting some
questions about using react query and
trpc in the latest nextjs so I
personally do not use react query or
trpc anymore and in this video I want to
explain why I don't have anything
against these tools in principle I think
they're still very useful outside nextjs
and I also think that the people who
build them and maintain them are very
talented people let's actually take a
look at why I don't use them anymore so
I'm going to use this remote Dev project
that is from my reacted next escore some
of you will recognize it and here we are
actually doing some data fetch so let's
actually start with react query so the
user can search for something and then
we get a list of results and the user
can click on one of those results to get
the detail right so here I clicked on
the at security so that's what we see
here let me actually zoom in a little
bit so you can see here that I can click
around and every time I click on one of
them we are loading the actual details
of that particular job item right very
standard very typical situation here I'm
using the same image for all of them by
the way so don't be confused they are
actually different right so you can see
the title here is front end devel veler
react and the company name at security
here the company name is Asen as so you
can see we're we're loading the relevant
details for the one that we clicked and
when I look in the network tab you can
also see that whenever I click on one of
them there is a new network request so
the data is being Fetch and most
importantly when I click on one that we
already saw there is a new network
request all right so how would we
implement this well traditionally
without react query you would have the
typical use effect right so you would
use use effect and then you can use the
fetch API to actually fetch the relevant
uh job item details right based on the
ID that we get here we're going to set
the loading is to set to true and
ultimately we get the data so we store
that in state and then here with is
loading we're setting that back to false
again right this is basically how you
learn react initially right so you have
use effect and that's how you fetch data
the downside of this is now if I click
on the first one you can see there is a
network request if I click on the second
one there is a new network request what
happens if I now go back to the first
one the one that we just fetched if I
click on the first first one there is a
new network request there is no caching
and when I go back to the second one
there is a new network request we see a
loading State there is zero caching so
literally every time we click on one of
them there is a new network request and
that is very inefficient right because
why are we making a new network request
we just requested this information 5
seconds ago so that's where react query
comes into play so let's actually
replace this with react query all right
so I have commented this out and I
replaced all of that with react query
here so with react quer you get the use
Query hook and it will give you the data
and an is loading flag as well so with
react query um there's three arguments
here that will specify so this ID is
like a caching key the second part is
the actual data fetching right so with
react query you still have to specify
how you want to do the actual data
fetching and then how long it should be
cached so what's the benefit of doing
this well if I now save here and now uh
Let me refresh here for a clean slate
all right so now we see the first one
here what if I click on the second one
well it's going to fetch initially it
has to fetch the data right but what
happens now if we go back to the first
one you can see that was instant right
if I now click on the second one you can
see that's instant there is no loading
State now I can click around between
these two because they have already been
fetched once and react query knows that
if it's an ID that it has seen before
right which is why we keep track of it
in here it can see that when you pass in
an ID and it's an ID that we have
already fetched for before react query
knows uh we already did this data
fetching for ID number five let's say so
we're not going to run all of this again
I'm just going to give you the data from
that number five from before so that's
called caching and let me show you that
in a network tab as well so if I click
on the last one here in the list you can
see there is a network request here and
there's no way around it initially you
need to actually fetch the data and now
let's say I click on the one uh on top
of that so there's another Network
request okay it's the first time so
you're going to have to get the data but
what happens now if we click on the last
one again you can can see I clicked
there there was no new network request
if I click on the one above it you can
see there is no new network request I
can I can click back and forth between
them there are no new network requests
because react query caches these job
items um when we fetch them now react
query can do many other things but I
would argue that this was the main
reason we were using react query and
this is still how I would do it in a
react feat app right so remote Dev is a
react feat app and in a feat app I would
still use re react query all right so
that's for feed right nothing really
changes for react feed apps or create
react app in case you're still using
that right so that all states the same
now in nextjs I would argue things
change a little bit so here I actually
converted the same app to uh the nextjs
framework so here it's the same app all
the same features and you can see when I
click on the second one you can see
there's a loading indicator there and if
I click on the third one there is a
loading indicator but what happens now
if I click on the second one the one
that we just saw that we already fetch
the data off you can see it's instant
when I click here it's instant right so
these first three I already fetched
their data so the next time I come back
to them I'm there's not going to be a
new network request because nextjs
actually caches that for me so let me
show you how it looks like in nextjs so
in nextjs we do not use use effect we
can actually make it async and then you
can do the data fetching directly here
in the component function body and then
if you do it like this next as will
automatically cash all of this and let
me prove that to you in the network tab
as well if I go to the second page here
let's say I pick the first one here you
can see there is an initial Network
request if I click on the second one
here there is there are actually two
Network requests we can ignore that but
you can see there is a network request
for every click what happens now if I go
back to that first one that I just
clicked if I click on that one you can
see it's instant there is no new network
request if I click on the other one you
can see it's also instant there is no
new network request because nextjs
automatically caches your fetch request
actually and how do we get the loading
State like we got with react query
though because if you look here you can
see we are still getting this spinner
here so how do you get that loading
State actually the loading State Works a
little bit differently so on the page in
a nextjs project so here on the page
component here is that component that's
actually doing the data fetching I can
wrap it in a suspense and then you can
specify a fall back so while the async
component is suspended right you can see
right while this is going on it will
render the f back here and this is the
component that actually shows a loading
spinner right so you can see here there
is a spinner in here right make sure you
add a key prop to the suspense so that
every time the ID changes the suspense
is triggered again very common Pitfall
actually right so next you ask comes
with built-in caching so that's why I
don't use react query for data fetching
in nextjs right so nextjs is very
aggressively cached actually so it will
actually automatically cach the result
of this fetch call this individual fetch
call whatever result of that is it will
actually cash that and that's actually
the most powerful cache in nextjs this
will persist even throughout deployment
and nextd S also caches the result of
this render right so your server
components this is your server component
the result of this render is a so-called
RSC payload react server component
payload so basically the render result
the render result itself is also
separately cached and there is also a
client side cache that nextjs manages
for us and that's actually why it's so
Snappy here because as I click around it
will actually use that client side cache
right so it will not make new network
requests to the back end because it can
see that we're requesting something that
has already been requested before right
so those are the three main caches in
nextjs now if you use the nextjs link
component which we actually do use here
in that in that list so for every item
in that list it's wrapped in this link
component where it will actually specify
what needs to happen to the URL when you
click on it this is actually prefetched
so as these links come into the viewport
nexts will automatically prefetch that
for me behind the scenes so then when
you click it there won't even be a
loading state it will be instant now
here we still get a loading State
because I'm in development here so that
link component prefetching is only
enabled in production mode that's nextjs
is very aggressively cached and that's
why I don't use react query in nextjs
however sometimes you still need to do
client side fetching right so there are
still some edge cases where you where
you actually want to do client side
fetching in that case the fetch API for
example is not automatically cached
right so this is only automatically
cached on the server so if you do client
side fetching you may still want to use
react query and usually that's the case
when you want to fetch data after a user
action for example infinite scroll right
so the user first has to scroll and then
you want to fetch data well you may want
to look into react query or you want to
do things like polling and some other
things in that case you may still want
to use react query in nextjs but
generally I don't use react query in
next J all right so what about trpc
let's go back to our feat example so TR
RPC is for client server communication
making that type safe so let's actually
go back to this example of fetching data
without react query just the traditional
way right so we just use use effect here
this is how you would do it
traditionally you would fetch the data
like this now one of the problems with
this is when we get data back here if
you hover data you can see it is typed
as any and we don't want to have anyes
in our codebase because any means
anything goes typescript should warn me
here hey this method does not exist but
as you can see because it's as any well
you can do anything this is not type
safe so the main problem here is you
don't have a good type here another
problem is of course you need to
remember the actual URL of the end point
that you're making that request to right
so this is not a robust way of
communicating with a back end all right
so then here I have an example of trpc
so you have to do some setup there is a
little bit of a boiler plate here but
the benefit is now I don't have to
remember the end point I can just use
trpc I can see what I have available
trpc oh I have a job python by ID method
on here and what do we want to do with
that well I just want to get data that's
called a query and actually I need to
pass some value to the endpoint if I
forget that typescript warns me here so
I get a warning here I need to specify
an input right if I pass in the wrong
input of a number type let's say I even
get a warning it should be a string
right so I'm just going to pass that ID
so I'm getting a job item by its ID now
the main benefit here is now when I
hover data you can see I'm getting the
actual type right so here now I get the
actual type so now if I make a mistake
on this and I think I can call some
method typescript will actually warn me
right and I can fix my mistake so now
this return value is properly typed and
another benefit is of course I don't
have to remember the actual URL of the
endpoint right so I can just use some
trpc object here and tapescript will
provide intelligence here to see what I
can do with that all right so then let's
go back to next JS how do we get those
same benefits without using trpc so trpc
is for when you control both the client
side as well as the server side right so
realistically you're not going to do a
fetch call to some third party API most
of the time typically you're going to
get this type of data from your own
database and you're going to use an OM
right so here for example with Prisma if
I get the job item by ID if I now hover
the data you can see I already get this
correct type and I also don't have to
remember some URL right so for getting
data I don't need to use trpc to get
these benefits server component allow me
to use Prisma directly here right so
with server components in xjs and your
omm you already will get the correct
type here right so to get those benefits
for getting data you don't need to use
trpc all right so that was for getting
data now what about mutations right
basically your postp put and delete
request well if you have some kind of
form let's say and when you submit the
form you want to add let's say a job
item to the database right so what you
would do typically before trpc again you
had to sort of guess the URL for the
endpoint and here you need to pass the
actual data but how do you know the
specific data or format and here I don't
get any intelligence here right I don't
get any relevant intelligence here so I
don't really know what to pass exactly
I'm just kind of guessing here also if I
get any return value let's say an error
or something like that right so if I get
any return value here you don't get this
properly typed you're going to get some
any type as we saw before all right so
what if we want to do the same with trpc
well you can use that trpc object so I
can use intelligence here to see the
options I have here so I don't have to
guess the the endpoint URL I can see
there is some option to create a job
item and I want to do a mutation so I
can do M mutate and then here I can pass
the data how do I know what data to pass
typescript tells me here so the input
needs to be an object with a title and
description right so here I can see what
I need to pass right so description and
title if I make a mistake if I make it a
number I get a warning here from
typescript so you can see all of this is
properly typed including any return
value I may get if I hover data you can
see data is going to be of this
particular shape right so with trpc you
get that very nice types saave client
server communication all right so then
why not use trpc in nextjs well nextjs
has another major Innovation and maybe
this is even the biggest one which is
server actions so server actions are
meant to mutate data on the server so
instead of using the onsubmit event
handler you would actually use the
action attribute and then here you can
invoke a server action so I actually
created a server called create job item
I actually put that in a separate file
we'll take a look at that in a second I
could technically also Define it in here
if I wanted to but I like to put them in
a separate file I can also do uh create
job item right I don't have to remember
a URL if I don't pass anything
typescript will warn me actually right
so it expects an argument here I know I
need to specify an argument here and
then here also you can see I'm getting
intelligence here so TP is telling me
hey you need to pass description and
title right so here I can say title if I
make a type mistake again you can see
I'm passing a number here I get a
warning here right so here you can see
type number is incorrect I can fix my
mistake right so with server actions I
also get that intelligence I don't need
to remember some URL endpoint and if
this returns anything if we uh get
something back here if I hover a result
you can see this has been automatically
inferred by typescript and so these
server actions you can call them from
anywhere from the client side server
side and so these server actions you can
invoke them anywhere and they provide
the same benefits and so the server
actions are very similar to just normal
local functions right and typescript can
infer whatever you return from that
function it can infer what you are
returning and so then here as a result
we get that type so let's actually take
a look at how we Implement a server
action like that so I like to put them
in a separate file I don't want to have
them lingering around in some components
they're very important functions
actually so I want to have a dedicated
place for them in my code base so with
us server at the top of the file every
function in here becomes a so-called
server action so here I have my server
action here I Define the input right so
you need to pass a new job item and it
should be an object with title and
description just like how you would
specify normal function with its
parameters right so you would give a
name for the parameter and then the type
and whatever type you specify here that
will automatically be uh suggested here
when you try to use it right so here we
got the intelligence because I have
typed this here I didn't need to do
anything else since surf actions are
basically like post API endpoints next s
behind the scenes will actually make a
post request to uh the back end and
since we cannot trust anything coming
from the client we do want to validate
that whatever we get here that this is
actually of the shape that should be
right so if we pass something that's not
of the correct shape we are actually
returning something here from this
function just like you would return
something from a normal local function
and whatever you return here this is
also what you will get here as the type
right so types skit will just give you
that type right so it could be this type
in case there is a validation problem
right and then we can do the actual
mutation in our database and then with
revalidate we can update the UI in the
same network request I have other videos
and server action so we can't spend too
much time on them but you can see that
we get the same results here with just
using server actions there is no
additional boilerplate required to make
all of that type safety work server
actions also have some additional
benefit for example here in forms they
provide Progressive enhancement which is
a very fancy word but it means that if
you just specify the server action like
this this will actually work without any
JavaScript enabled and if you actually
do provide some more code like what we
we're doing here and maybe here you also
want to have maybe a toast message in
case there is an error if you do it like
that it will actually need JavaScript
but then still this form will be
prioritized in hydration and the server
actions are also integrated with some
powerful hooks like use form status to
get a pending State and also use
optimistic to get optimistic UI one
downside here is I did type it as an
object like this realistically like I
just said we don't really know what we
get here you cannot trust any anything
coming from the client and with
typescript you do want to be as precise
as possible so a more precise type for
this input is actually unnown we don't
really know what we're going to get this
would be a more precise type and then
you need to validate it with for example
zot which is actually very similar to
how you would do it in trpc as well so
that doesn't change you would run it
through some schema first and then once
that is successful uh you would use that
variable right so then you would use
validated job item. dat. tile. data and
then here here you also get the proper
type right so after validation you do
get the right type here on the backend
side now the downside of doing this is
now when you use the server action since
it's typed as unknown we don't really
know what we need to pass here right so
now we lose that intelligence so that's
one downside if you properly type it you
do lose the intelligence now there are
some rapper libraries that will fix that
so my guess is that we will get some
rapper library for Server actions that
that will fix some of its downsides now
one major downside of server actions
that is going to be hard to to fix is
that you cannot easily use them outside
nextjs so if you also want to support
let's say a react native mobile app
client you can't use these server
actions so if your plan is to support
clients outside nextjs you may want to
stick to trpc so if you're a little bit
confused by now completely normal nextjs
has really changed the landscape of web
development in my opinion if you want to
master latest react and nextjs I highly
recommend you go through my professional
react and nextjs course in which we
start from absolute scratch and by the
end we're building some really cutting
edge nextjs applications you can find
the link in the description so just to
sum up this video I would still use
react query and trpc in a react feed app
for example but in a nextjs application
I'm probably not going to use react
query or trpc I'm doing some client side
data fetching in some Edge case in which
case I would use react query or I'm
planning on supporting clients outside
nextjs in which case I would use trpc
for my endpoints thanks for watching
this video and I hope to see you the
next one bye
浏览更多相关视频
![](https://i.ytimg.com/vi/wd639F9aKU0/hq720.jpg)
What You Need to Know Before Learning NextJS
![](https://i.ytimg.com/vi/DKs6nOcl5Ws/hq720.jpg)
Pure React vs Next.js | What’s Happening in React?
![](https://i.ytimg.com/vi/yUm-ET8w_28/hq720.jpg)
React's most dangerous feature
![](https://i.ytimg.com/vi/DG_WT8Gwzho/hq720.jpg)
Next.js Fetch Data the Right Way (with a Data Access Layer!) (Security, Auth, Cache, DTO)
![](https://i.ytimg.com/vi/N2_wi90zib8/hq720.jpg)
I Was Surprised How Next.js Cached My Server Components
![](https://i.ytimg.com/vi/RBM03RihZVs/hq720.jpg)
10 common mistakes with the Next.js App Router
5.0 / 5 (0 votes)