Next.js Discord

Discord Forum

Equivalent of context for app router?

Unanswered
Thai Ridgeback posted this in #help-forum
Open in Discord
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 😮‍💨

1 Reply

Thai RidgebackOP
Oh, apparently there was an unstable_cache function which you can revalidate

Is 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? 🤔