Next.js Discord

Discord Forum

cache third party in client component

Answered
B33fb0n3 posted this in #help-forum
Open in Discord
how to cache a function which calls a thirdparty? I am currently using
export const getAuthUser = cache(async () => {
    console.log("getAuthUser called");
    const user = await Auth.currentAuthenticatedUser(...);
    const graphUser = await API.graphql(...);

    return {
        data
    }
});

But when I call both functions:
    const callOne = async () => {
        const data = await getAuthUser();
        console.log("fromOne data: ", data);
    }

    const callTwo = async () => {
        const data = await getAuthUser();
        console.log("fromTwo data: ", data);
    }

The message for the fetching "getAuthUser called" will be send twice. I am using app directory
Answered by aardani
now theres 2 ways to do 1, either via fetch() or use Server Actions
View full answer

56 Replies

@aardani where did you call the two function and where did you define `getAuthUser`?
the two functions are not called by default, only when I click the buttons:
'use client'

import {getAuthUser} from "@/app/dashboard/(pagestuff)/actions";
import {Button} from "@aws-amplify/ui-react";

export default function TestComponent() {
    const callOne = async () => {
        const data = await getAuthUser();
        console.log("fromOne data: ", data);
    }

    const callTwo = async () => {
        const data = await getAuthUser();
        console.log("fromTwo data: ", data);
    }

    return (
        <>
            <h1>TestComponent</h1>
            <Button onClick={callOne}>1</Button>
            <Button onClick={callTwo}>2</Button>
        </>
    )
}

The getAuthUser is defined in an actions.js
@aardani cache() is to dedupe calls within a single rendering pass in server components
oh ok. How can I archive the behavior? I looked inside the docs at the Data Cache, but for something like user data it should only hold for the next refresh of the page. So the user enters the website, the getAuthUser get called and then the user do stuff on the website and whenever I call the getAuthUser again only the cache will be returned. But you should also be able to revalidate the data via the code. This means that the next time the data is fetched, it really is revalidated by the server
the request memoization looks perfect for me: https://nextjs.org/_next/image?url=%2Fdocs%2Fdark%2Fdeduplicated-fetch-requests.png&w=1920&q=75&dpl=dpl_DYH3zLcMVZxDqvwpmWDDz1GDip82

but for me it looks like that's only supported with the fetch function
wel you can use unstable_cache()
why do you need to persists getAuth between requests?
@aardani wel you can use `unstable_cache()`
I tried to use it, but it does not work and it will be a production environment later :/
@aardani why do you need to persists getAuth between requests?
to reduce the amount of fetching
ah
lol xD
unstable_cache works for me
you are not in a production environment? 🤔
i am not but have tried deploying it
one other way is just to call your own backend api i guess
create a route handler in Next.js so that you can use fetch()
@aardani i am not but have tried deploying it
when I try to use it it just give me this error:
its being used differently
export const cachedData = await unstable_cache(
    async () => {
        console.log("unstable called");
        const user = await Auth.currentAuthenticatedUser();
        return user
    },
    ['user-cache'],
    {
        tags: ['userdata'],
        revalidate: 10,
    }
)()
you dont declare it outside the react component, it has to be inside and immediately called
oh, I can't reuse it in other components? Or do I need to copy the same code in every component?
you can
are there any docs or examples about it?
this is how i set up my unstable_cache
@B33fb0n3 when I try to use it it just give me this error:
you can't do this coz you can't call unstable_cache in client-side codes
like it has to be in a server environment
Data Cache concerns those that are in the server,
if you need it to run onClick, it has to send an API request to the server to trigger the Data Cache
@aardani you can't do this coz you can't call unstable_cache in client-side codes
oh and I just tried it and wonder what I read wrong lol
@aardani if you need it to run onClick, it has to send an API request to the server to trigger the Data Cache
so the client send a request to the server and the server checks the cache and else revalidate, right?
yep
same as if you were using fetch
first fetch to the server from client, this is not cached,
but you need cached data from backend thats why you use server-side fetch thats cached
client --- 1 ---> next.js server --- 2 ---> backend api / external data
Data cache happens at 2, not 1
thats why u can't call unstable_cache at 1
now theres 2 ways to do 1, either via fetch() or use Server Actions
Answer
@aardani thats why u can't call unstable_cache at 1
that makes sense. I just saw Router Cache maybe I can store the function returns inside it. But for me it looks like only routes 🤔
No router cache can't store function returns
That one cache the entire page in the client
it has something to do with prefetching pages and navigating back and forth
Use React Query if you want to cache client-side function calls haha
or useSWR
@aardani No router cache can't store function returns
oh ok. Than I think I will do it with the server actions and if I can't get that working, than via the fetch from the api
@aardani or useSWR
I tried to useSWR, but for me it looks like that's not possible...
I tried it like that:

    const {data, error, isLoading} = useSWR('my/url', getAuthUser)

    if (!isLoading) {
        console.log("data: ", data);
    }
by the way the 'my/url' is not replaced by me. It's really like that inside the code :fine:
@B33fb0n3 , useSWR is also a stale data manager, you need to use fetch() or axios() or ServerAction inside the getAuthUser
that sucks... then I will do it directly with server actions
yes but it can automatically determine if you need refetching or not without messing with useEffect and what not
well depends on your use case
you probaly dont need that if you just want onClicks
but its nice to have for component that needs that data
yea, for me it's the simplest example I could made to show my problem. Currently I have a client side context and everytime a specific components is rendered a useeffect will be called and the data is fetched and set to the context.. But then I won't have any control over it...