cache third party in client component
Answered
B33fb0n3 posted this in #help-forum
B33fb0n3OP
how to cache a function which calls a thirdparty? I am currently using
But when I call both functions:
The message for the fetching "getAuthUser called" will be send twice. I am using app directory
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
56 Replies
@B33fb0n3 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
where did you call the two function and where did you define
getAuthUser?@aardani where did you call the two function and where did you define `getAuthUser`?
B33fb0n3OP
the two functions are not called by default, only when I click the buttons:
The getAuthUser is defined in an actions.js
'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
cache() is to dedupe calls within a single rendering pass in server components
@aardani cache() is to dedupe calls within a single rendering pass in server components
B33fb0n3OP
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
B33fb0n3OP
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
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()`
B33fb0n3OP
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?
B33fb0n3OP
to reduce the amount of fetching
ah
B33fb0n3OP
lol xD
unstable_cache works for me
B33fb0n3OP
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()
its being used differently
B33fb0n3OP
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
B33fb0n3OP
oh, I can't reuse it in other components? Or do I need to copy the same code in every component?
you can
B33fb0n3OP
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
B33fb0n3OP
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
B33fb0n3OP
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
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
B33fb0n3OP
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
B33fb0n3OP
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
B33fb0n3OP
I tried to useSWR, but for me it looks like that's not possible...
I tried it like that:
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 
@B33fb0n3 , useSWR is also a stale data manager, you need to use fetch() or axios() or ServerAction inside the
getAuthUserB33fb0n3OP
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
B33fb0n3OP
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...