how to revalidate data?
Router.refresh() purges all the caches if I understand correctly. How would you invalidate a cache after running a mutation using trpc on a client component?
make a request to an API route to invalidate a tag or a path :) or in your trpc mutation (if its running on the same server) revalidate it
Wdym by make a request to an API route to invalidate?
You want to invalidate items in Next's data cache?
I’ve fetched a list of items in a server component And the server component has a client component The client component creates a new item How do I show the updated list without a hard refresh
You need to make an HTTP request to the Next server that calls
revalidatePath()from your client component
Wow that seems unnecessarily complicated 🥲 Do you have a good understanding of the 4 types of caches
That's an excellent question
I’m so confused after reading the docs
If you ask questions I can try to answer them
It seems like a lot of people are as well from the GitHub threads I’ve read How do you use the app router with t3 is my question Previously without the app router, i define everything in the trpc router files
And then just call them in componentS
read this first
What does this mean If it’s defined why would need to wrap it around a suspense boundary Thanks for sharing. I read all of it. Seems like most things are still in the experimental stage? From what I can tell, using t3 there’s no stable and easy way to 1. Mutate on the client and revalidate the data fetched in server components 2. Fetch on window focus if the data were fetched in a server component 3. Do all the fancy cache stuff that NextJS offers 4. Use server actions (what’s the benefit of this anyway compared to trpc mutation, is it no JS?) 5. Stream data in with which react query can use
It's defined because it's in a suspense https://papertrail.biblish.com/blog/trpc-and-app-dir Read that as well
I see Let me read that I read it So it’s an “initialData” approach that solves the roundtrip problem of “1” since it off loads the logic to the client side so if I invalidate the cache, it will refetch. It also solves “2” since it’s using client side. It also solves “5” since I can render other components and wrap the client component in Suspense and once it’s ready, react query can be used due to initialData. Am I right so far? There is the downside that I have to write a similar query for every query tho
Yes, pretty much I'm not sure what you mean
Rather than use query once in the client component, we are fetching once on the server and also using query on the client Also this means that I’ll have to mainly use client components (only the fetching data is in server components, not the rendering) Should I be using any of the NextJS cache stuff And server actions To get around this, I read Julius’ docs again and it seems like I can use “useSuspenseQuery” together with the experimental “ReactQueryStreamedHydration” to achieve the same behavior In conclusion, 1. Server actions are experimental with t3/trpc 2. Nextjs cache are experimental with t3/trpc 3. We can use server components two ways: a) using useSuspenseQuery with initialData b) using useSuspenseQuery with the experimental ReactQueryStreamedHydration Question: 1. Are server actions better than trpc mutations? If so, how?
Well yes, next app router does implicitly use suspense through the file structure thiugh Yeah, it might be a bit finicky but it depends. If you really care, you can extract just the data rendering to client components, and it shouldn't be the biggest deal depending on what you ship to the client I don't have an example at the moment, but nothing is stopping you from creating a caller/a vanilla client and just calling the mutations, if that makes sense
Thanks a lot for clarifying all these things, I appreciate it How did you find the two links you shared with me by the way?
The first one is pinned in the trpc discord, the second one was written by Josh, who's fairly active on this server
The approach in the blog post doesn't feel as ergonomic as what I generally expect from tRPC 😦 Also we run into the issue where "just fetch where you need the data, it de-dupes" is still broken here? If you need data in a layout and a page that belongs to the layout, this hits the server 2x ? Really hoping for a nicer fix here where the trpc call on the server has parity with the next fetch patch and all their cache stuff. Unless I'm horribly misunderstanding something
if you don't re-create the client then why would it be broken?
Because it doesn’t use the next cache When I call a procedure from layout and a page that belongs to the layout, it runs on server 2x
you're going to have to be more specific than "the next cache", there's like 4 different caches
Sorry. It doesn’t use a cache period At least in the ct3a setup I’ve installed It has to be wrapped in reacts cache fn afaik, which is not very intuitive at all
interesting, you're right I was under the impression that trpc uses fetch, next's overwriting of the global fetch would just be used instead
Yea.. it feels like every day I’m switching between really enjoying app router and then hating it Never spent so much time trying to decide how to structure my components for a page
im going to have figure this out lol 😭
It’s really frustrating and now I’m thinking of going back to remix lol I like tRPC. I like app router. I’m not smart enough to figure out the hard cache/invalidation stuff In pages ct3a, everything is easy and solved. In app router it feels, as is precautioned in the setup, unfinished
Having the same problems here as well, it seems that app router is really only viable for simple, non-interactive apps, and is just too tedious to work with for certain features. Really liked server components, but in the end I'm probably just going to wrap my root component in "use client" to ignore it pretty much because of hard requirements like global state
I do want to ping @Josh here, interested if you have anything to say on this?
Reading I actually need to rewrite this, I've updated my patterns quite heavily I'll rewrite it later, I'm on vacation rn so not sure when I'll get it up but basically, I've found the best approach is to get all your basic page data in the rsc, then use mutations to call router.refresh in your onSuccess And wrap the router refresh call in a transition and watch the is transitioning variable to track when the refresh is done This outlines it a bit https://github.com/GentikSolm/t3-app-dir Read the readme for more info there
See the fact that you have changed basically your entire set up in the span of like less than 2 months doesn't inspire confidence in app router 😭 Also refreshing all of the data for every change seems like a bad idea?
Depending on the change yes Hahahaha I also have a very "break often fix fast" mindset
But you don't get to choose do you
Wym I'm our only developer so I change everything at my own whim lmao Hence why I can move so fast If you're changing something individually my pattern has been to get data in rsc, then optimistically update in onSuccess. Most of my routes are already dynamic so I don't need to revalidate
I’ve been working in the same page in my app for 2ish weeks now and I swear I’ve tried every configuration of client/server and data load architecture So I’m experiencing the same thing with having to change patterns often
lmfao I meant you don't get to choose what changes you use router.refresh for
The way I look at it is that this stuff is wildly bleeding edge. We are the early adopters of this stuff and we have to figure out the best patterns for this ourselves and that's a risk/ work in willing to take on So I'm totally fine with having to change often and figure out stuff on my own cause I think it's fun and interesting Well what I said still applies, depending on how you use refresh changes you're other data syncing patterns and since I'm solo I choose which pattern to use when and where to test new stuff out I'll say this, my entire site is built with app dir and I've been extremely happy with it with this in mind. If you don't have this mindset it's going to be much more difficult Another way to think of it is that app dir is crazy new and freshly released in the broader scope of things. It's going to take time for stuff like trpc to really catch up and figure out how they want to handle things like RSCs Thank you for tagging btw, this is very much my favorite cup of tea If I'm reading this correctly then yes it's a misunderstanding. If you have a dynamic layout that prefetches data, you can tell your page to not fetch on load saving you the duplicated request
But there’s no native way to share data from layout downwards a la SvelteKit/Remix Shit I’m tired af spelling “no” as “know” smh
Yeah just use a context I actually do that in my app
Yea this goes back to my point though, there’s workarounds for a lot of these things, but their recommended way in this case is “just fetch where you need the data, we de-dupe” which is just not really always applicable unless you’re using their fetch I largely agree with you on the “it’s bleeding edge, expect shit to not be nice” It just feels largely counterproductive for me to bother with /pages right now, knowing my curiosity I’ll wanna rebuild in app router as soon as I ship. But the app router experience is frustrating so we’re just in an unfortunate grey area right now
Also When I'm sober I can help much more lmao
The only real to invalidate data is to pass initialData to client components and use react query is basically what I'm saying. revalidateTag is basically not an option, and if we don't use react query we will have to use refresh in every scenario which might not be the best idea
I was thinking of just defining an object that looks like a tRPC router. Write some sort of thin wrappers that make mutations server actions, and queries just regular functions lol
If you can't use refresh I'd just optimistically update + revalidate
I feel like I'm missing something Revalidate how
Path I think if you revalidate path then next time the user visits it will re run That needs testing though Again, to be fair, I'm currently pretty drunk and on vacation so I'll need to do a bit more digging when I'm back
but then I need to use server actions and we're using an external API and yada yada I think your old setup probably just works best for us lol
@iDarkLightning what does @jack mean what he said the fetching is gonna happen twice on the server? Why would it happen twice? Here
If you do a fetch in different components that are different points in the component tree, next is supposed to dedupe the requests It doesn't seem to work with the vanilla trpc client, at least with the link set up on ct3a
I see What’s a use case that you would need to fetch the same thing on different components (in one tree)?
you fetch the user in the layout to do an auth redirect, you fetch it somewhere else to display user data
Ok Usually if I need that user data so often I’ll just add it to the user session I’m pretty sure useSession for nextauth dedupes
use session is client side
Yea Maybe I haven’t come across a use case where I need more user info than the basic ones But say in the layout page I’ve requested the user data once, I just store it in the augmented user object and useSession will give me what I need from there on
Just anytime you want to render data from the same request in two components
Yea but I can’t think of a use case where that’s needed Well written components should do one thing, isn’t that why we have separate components?
Two different things can rely on data from one fetch I'm a bit confused this is a very very common thing lol
I’ve never come across it Usually each component fetches the data that it needs For example say it if I have a dashboard and there’s a Stats component, and there’s a list of users that belongs to the project (UserList component) The way I do it is id query for the stats in the stats component, and query for the user list in the UserList component
A layout that shows a users profile picture and username, and the page shows other data that depends on user data for example
For example let's say you have a multi tenant app, and you need the org info in several places
This is exactly the pattern that causes this issue
I think I was slightly unclear, it's not just the same data**
The biggest culprit is that, unlike other frameworks like SvelteKit and iirc Remix, you can’t pass data from layouts downwards as a feature of the framework. Next/Vercel recommends just refetching because it’s de-duped
It makes one network request instead of 30
You can just augment the user object. User is the only use case I can think of
In the most respectful way possible, you haven't built complex enough apps if you can't think of use cases for this What do you mean here, you're moving into the client boundary
Usually they would need different information of the org right. I try to select the parts I need for each request. If they’re truly intertwined (one is a child of the other), then I’d just pass them down as props
I don't want to render on the client, the whole point is I do it on the server You cannot pass them down as props from the layout
Not for layouts but normal components I see what you mean
What if the components are siblings
So let’s say I need the org name in both the layout and the not layout component Then id need to fetch twice Is that what you mean
Next recommends you fetch twice, because they will dedupe
Fetch in the parent
What happened to components only having one purpose
To put it simply, other frameworks have support for this feature (passing data from layouts down). Next explicitly mentions that they don’t support this, and explains their own solution. If this wasn’t a common, or at the very least not uncommon, pattern, then why is every major meta framework accounting for it?
Wdym each component is still rendering what they should no?
It's rendering what they should but it still has irrelevant logic Regardless okay If you have 7 different components on a page And they all make an individual network request for data for only that component You are making 7 network round trips to display the data on one page
I see Ok so you’re saying instead of 7 network requests, we should be making one
You should be making as few as possible
Right Before I thought you meant that instead of making two identical requests we should be making one. This was confusing because it’s rare that two components would need identical data
It's not Trust me it's not rare at all
So next is supposed to combine all the requests on the same page into one? Ok
Next is supposed to dedupe requests, so all the same requests should dedupe
Ok Do you prefer to use ReactQueryStreamedHydration or initial data ReactQueryStreamedHydration seems more ergonomic but it’s experimental I think
I haven't used react query streamed hydration yet
Alright Thanks for the discussion
Can you give me an example? I looked at NextJS docs and it’s also talking about user
I see So it’s recommending us to use fetch instead of forwarding props I guess that’s more ergonomic
The user example is a very common one yea Think about a page with a sidebar, header, sub header, all in different level layouts that need user data
Makes sense 👍🏻
Want results from more Discord servers?Recommended Posts
Sitemaps - Is there something fundamental i'm misunderstanding about sitemaps?Hello! I'm currently exploring how to best generate dynamic sitemaps for a Next.js-powered website.useRouter import not working?just following the docs and trying to add shallow routing. In my app/page.tsx i have the following use query on success/error/settled are being deprecated.Since the above call backs are being deprecated, I'm attempting to implement the suggested solution TRPC pass res to ctx using app routerI used the template provided by trpc, ctx doesn't contain req or res. I managed to pass the req but trpc in server componentsHas anyone been able to use trpc to access the db in a server component? I’m able to access it usintRPC not returning stringI have a procedure that generates a presigned url and sends it to the frontend. When I print the urlClean ArchitectureAny suggestions as to how can one have a maintanable and scalable project structure where every servError with in expo @ create-t3-turboWhen trying pnpm run dev on the base app after setting up discord and db url env vars, the nextjs apCan npx execute packages without having the package installed?In a lot of places i see people saying that npx can execute packages without instlalling them but whAPI Design: PDF generation in a REST-APIWe have a REST-API (NextJS) that uses react-pdf for PDF generation and s3 as a storage for these. OTRPC fails to work on server components in Vercel environmentGetting a Application error: a server-side exception has occurred (see the server logs for more infoToo many re-rendersWhen I render this component that is a client component of a dashboard slug, it breaks the entire paUnwanted Re-renders with Custom Hook in Next.js (T3)Hello everyone, I'm currently working on a Next.js project and I'm facing an issue with unwanted reConfiguring Clerk on the latest release of t3 with tRPCCould anyone share a working example of configuring Clerk on the latest release of t3 with tRPC? I'mNextauth jwt configurationI am making a simple task manager application using google apis with the t3 stack and I am having diHow do I fix this query, I was following a tutorial that doesn't use the t3 stackI'm trying to replicate this query (shown below) into t3 stack but the "onSuccess" property doesn't Button creates vertical gap in grid, button doesn'tThis is possibly a really really dumb question, but why does the button result in a vertical gap in Is anyone using the nextjs app router for their frontend and pages for trpc?If you could share an example repo I'd love to see how you've implemented thisSession exists in server component, not in trpc context.Inside of a server component I call: ` const session = await getServerAuthSession(); console.loQ: About System Design😦