Equivalent of context for app router?
Unanswered
Thai Ridgeback posted this in #help-forum
Thai RidgebackOP
Hi, I'm building my first app router app, and trying to wrap my brain around the new "best practices".
One thing that's very unclear to me is what is the equivalent of what use to be context, for the pages router?
Like, let's say I have a database table called "users", with some basic info about the current user. I want to load that info into the navbar, and I want to load that info into a completely separate component somewhere on the page, but I don't want to do two database requests because that would kill performance.
How do I access the same data in these two places? In a client component, it would be simple, I'd just use a context. But what about a server component?
From what I've seen in the docs, it looks like the recommended solution for this very frequent use case is... To cache all my database requests for an hour? That can't be right? I do want to run the database request on every page load, just in case the data has changed, but I only want to run it once. A cache isn't what I'm looking for here.
This is the page of the doc that seems to talk about this:
https://nextjs.org/docs/app/building-your-application/caching#request-memoization
But since I use a 3rd party library for my db access, they recommend I follow this instead:
https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#fetching-data-on-the-server-with-third-party-libraries
Except using the react cache, it doesn't look like I have any way to manually tell the cache to revalidate? (e.g. after updating the user's database entry, or on a new page load)
So... what's the recommended solution exactly? This seems like a case that would be way too frequent not to be handled by next but I can't find anything on this 😮â€ðŸ’¨
One thing that's very unclear to me is what is the equivalent of what use to be context, for the pages router?
Like, let's say I have a database table called "users", with some basic info about the current user. I want to load that info into the navbar, and I want to load that info into a completely separate component somewhere on the page, but I don't want to do two database requests because that would kill performance.
How do I access the same data in these two places? In a client component, it would be simple, I'd just use a context. But what about a server component?
From what I've seen in the docs, it looks like the recommended solution for this very frequent use case is... To cache all my database requests for an hour? That can't be right? I do want to run the database request on every page load, just in case the data has changed, but I only want to run it once. A cache isn't what I'm looking for here.
This is the page of the doc that seems to talk about this:
https://nextjs.org/docs/app/building-your-application/caching#request-memoization
But since I use a 3rd party library for my db access, they recommend I follow this instead:
https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#fetching-data-on-the-server-with-third-party-libraries
Except using the react cache, it doesn't look like I have any way to manually tell the cache to revalidate? (e.g. after updating the user's database entry, or on a new page load)
So... what's the recommended solution exactly? This seems like a case that would be way too frequent not to be handled by next but I can't find anything on this 😮â€ðŸ’¨
1 Reply
Thai RidgebackOP
Oh, apparently there was an
Is this correct/the intended way to do this then?
The IIFE makes me think this is wrong but if I just tag this "user", then whenever one user updates their info, it's going to invalidate every single user's info, right? 🤔
unstable_cache function which you can revalidateIs this correct/the intended way to do this then?
import { Collections } from "../mongodb";
import { User } from "@/model/user";
import { revalidateTag, unstable_cache } from "next/cache";
const tag = (userId: string) => `user:${userId}`
export const getUserById = async (userId: string) => {
const callback = async () => {
const users = await Collections.users()
const user = await users.findOne({ userId }, { projection: { _id: 0 }})
return user
}
return await (unstable_cache(callback, ["user"], { revalidate: 3600, tags: [tag(userId)]}))()
}
export const updateUser = async (user: User) => {
const { userId, ...$set } = user
const users = await Collections.users()
const result = await users.findOneAndUpdate({ userId }, { $set }, { upsert: true })
revalidateTag(tag(userId))
return result
}The IIFE makes me think this is wrong but if I just tag this "user", then whenever one user updates their info, it's going to invalidate every single user's info, right? 🤔