Nextjs is not updating content data from Sanity
Unanswered
Schneider’s Smooth-fronted Caima… posted this in #help-forum
Original message was deleted.
184 Replies
Northern Mockingbird
Hi, did you ever resolve this issue? I am having this same problem and I just found this post in the forum
Dwarf Crocodile
same here
Northeast Congo Lion
have you guys got static generation?
Dwarf Crocodile
how do I check that?
Northeast Congo Lion
are you just
npm run build
npm run start
with a simple fetch
Dwarf Crocodile
npm run dev
well vercel runs npm run build when I push my code
well vercel runs npm run build when I push my code
Northeast Congo Lion
when you do
npm run build in consoleyou will see a print of what is Static generation build or static gen server
Dwarf Crocodile
let me run that really quick locally
Northeast Congo Lion
so static gen build is only built once when you push to vercel
Dwarf Crocodile
How does this interact with sanity?
Northeast Congo Lion
but if you dont have something like
fetch(url, {
next: {
revalidate: 60
}
});Dwarf Crocodile
do I need to put this everywhere I fetch data?
Northeast Congo Lion
i generally create a function that wraps the fetch
and returns promise or json
like a util function
Dwarf Crocodile
so something like this?
Northeast Congo Lion
then u can just call
getPageData();Dwarf Crocodile
Sorry this is what I have rn
Northeast Congo Lion
exactly
i am not familiar with sanity to be honest
Dwarf Crocodile
well I just added the revalidation part
Northeast Congo Lion
so now
with this data call for ur main page
Dwarf Crocodile
It definitely has to do with vercel though cause when Im running my code locally I see the sanity studio changes immediately
Northeast Congo Lion
nextjs will see it has revalidate on fetch and create 60 second windows basically
@Dwarf Crocodile It definitely has to do with vercel though cause when Im running my code locally I see the sanity studio changes immediately
Northeast Congo Lion
yes bcause next dev is always live content
next build is not
unless u use revalidate
next dev = no cache
Dwarf Crocodile
Ah ok this is starting to make sense a little
Northeast Congo Lion
hence why u see instant updates
Dwarf Crocodile
so I dont have to do this in every file
can you show me how I would wrap this
please
Northeast Congo Lion
show me ur page
code
for whatever page isnt updating
Dwarf Crocodile
Ok just one second
here im fetching servies but all my files are the same
so here is the fetch and then above is the home page where I call getServices()
Northeast Congo Lion
okay so
i would refactor this
create a function like getPageData
or tbh, just add revalidate
in each page actually.
so in getServcies()
stick the next: revalidate in
Dwarf Crocodile
ok
just one last question what do I do for this one?
this?
{ slug, next: { revalidate: 60 } }Northeast Congo Lion
nah
just the same man
next just needs to check if revalidate
Dwarf Crocodile
Im just not sure where to add the "next" option in this last one haha
since I need to pass the slug also. Does this look ok?
@Dwarf Crocodile since I need to pass the slug also. Does this look ok?
Northeast Congo Lion
oh
sorry, thats right
fetch(url, {
body: {
slug:
},
next: {...}
})if posting ^
Dwarf Crocodile
thank you so much dude. Im about to test this and will report back if it works now
I spent all morning trying to figure out what was wrong
@Northeast Congo Lion oh
Dwarf Crocodile
damn I think it still doesn't update
Northeast Congo Lion
pls run
npm run buildin console
show output
Dwarf Crocodile
k just a sec
Northeast Congo Lion
btw
it wont instant update
60 = 60 seconds
so nextjs works like
initial page built, and served to client.
60 seconds passes
when next user visits, nextjs will start building new page in background
and when it is ready, next well then serve new page.
Dwarf Crocodile
Northeast Congo Lion
kk
so u see (static) and (dynamic)
they have little symbols
if u look at the route (app) list u will see what is static & dynamic
static = built once
server = per request
server = per request
and SSG is what we're aiming for.
can u paste ur code pls
into chat
Dwarf Crocodile
how do you achieve SSG?
sorry for which part?
Northeast Congo Lion
homepage
Dwarf Crocodile
yeah just one second
import Image from 'next/image';
import Hero from '@/app/components/Hero';
import { getServices } from '@/sanity/utils';
import servicesSplash from '@/public/images/services.jpg';
import ServiceCards from './components/ServiceCards';
import BlogCards from './components/BlogCards';
const Home = async () => {
const services = await getServices();
return (
<div id='home' className='-mt-20 '>
{/* HERO SECTION */}
<Hero services={services} />
{/* SERVICES SECTION */}
<div className='flex flex-col'>
<div className='container py-20 md:py-32 text-center'>
<h2>Smart Solutions, Legal Success</h2>
</div>
<div className='grid lg:grid-cols-2'>
<div className='relative hidden lg:block'>
<Image
src={servicesSplash}
alt='services'
fill
sizes='100vw'
className='object-cover filter grayscale-[0.2]'
/>
</div>
<ServiceCards services={services} />
</div>
</div>
{/* BLOG SECTION */}
<div className='container flex flex-col py-20 lg:py-40'>
<div className='flex items-center'>
<span className='w-10 bg-lightText mr-2 h-[1px]' />
<h4>Everything new</h4>
</div>
<h2 className='pt-4 pb-10 mb-10 border-b-[0.5px]'>
Read our latest insights
</h2>
<BlogCards />
</div>
</div>
);
};
export default Home;Northeast Congo Lion
kk
at the top add this to page
export const revalidate = 15;Dwarf Crocodile
above the imports?
Northeast Congo Lion
yup
top of file
@Dwarf Crocodile above the imports?
Northeast Congo Lion
did it work?
@Northeast Congo Lion did it work?
Dwarf Crocodile
I broke something somehow lol
just a second
Northeast Congo Lion
eeek
@Northeast Congo Lion https://tenor.com/bTvu5.gif
Dwarf Crocodile
yeah Im not sure what happened but when I added that line I got an error and now when I removed it the error wont go away haha
Northeast Congo Lion
Show error
Dwarf Crocodile
Northeast Congo Lion
Show homepage code
Dwarf Crocodile
import Image from 'next/image';
import Hero from '@/app/components/Hero';
import { getServices } from '@/sanity/utils';
import servicesSplash from '@/public/images/services.jpg';
import ServiceCards from './components/ServiceCards';
import BlogCards from './components/BlogCards';
const Home = async () => {
const services = await getServices();
return (
<div id='home' className='-mt-20 '>
{/* HERO SECTION */}
<Hero services={services} />
{/* SERVICES SECTION */}
<div className='flex flex-col'>
<div className='container py-20 md:py-32 text-center'>
<h2>Smart Solutions, Legal Success</h2>
</div>
<div className='grid lg:grid-cols-2'>
<div className='relative hidden lg:block'>
<Image
src={servicesSplash}
alt='services'
fill
sizes='100vw'
className='object-cover filter grayscale-[0.2]'
/>
</div>
<ServiceCards services={services} />
</div>
</div>
{/* BLOG SECTION */}
<div className='container flex flex-col py-20 lg:py-40'>
<div className='flex items-center'>
<span className='w-10 bg-lightText mr-2 h-[1px]' />
<h4>Everything new</h4>
</div>
<h2 className='pt-4 pb-10 mb-10 border-b-[0.5px]'>
Read our latest insights
</h2>
<BlogCards />
</div>
</div>
);
};
export default Home;same as before I think
Northeast Congo Lion
What about the fetch
Can you remove validate from them please
@Northeast Congo Lion Can you remove validate from them please
Dwarf Crocodile
I did still same thing
looks like I broke my <BlogCards /> component. I tried putting the export validate in there as well
Northeast Congo Lion
Nah
Dwarf Crocodile
but even though I removed its still broken
Northeast Congo Lion
Just pages man
make sure it’s only on page.js
Dwarf Crocodile
I'll put it in pages only
Northeast Congo Lion
the export yeah
Dwarf Crocodile
Should I leave the next: validate in the queries?
Northeast Congo Lion
Nah
Export does it as well
So one or other
Dwarf Crocodile
ok trying with this now
Not sure what happened to BlogCards it's somehow broken now. But I can fix that later
you could pass revalidate to sanity fetch like this
sanity has a good example for next
https://github.com/sanity-io/next-sanity/blob/d8cde2d4a42d067f772a1e83cfe0a179b8a80308/app/sanity.fetch.ts#L29
client.fetch(query, { slug }, {}, { next: { revalidate: 60 } })sanity has a good example for next
https://github.com/sanity-io/next-sanity/blob/d8cde2d4a42d067f772a1e83cfe0a179b8a80308/app/sanity.fetch.ts#L29
and you could create a
https://github.com/sanity-io/next-sanity/blob/main/app/api/revalidate-tag/route.ts
route.ts and setup a webhook on sanity to revalidate the data after you update the data on sanityhttps://github.com/sanity-io/next-sanity/blob/main/app/api/revalidate-tag/route.ts
Dwarf Crocodile
Ok I figured out what my error was. now back to try to fix the caching issues. Thanks for chiming in @Ray
So you don't think the suggested solution above of adding
So you don't think the suggested solution above of adding
export revalidate = 15; would sufice?Dwarf Crocodile
so if not passing a slug when Im fetching all my services for instance, do you would it be like this?
client.fetch(query, { }, {}, { next: { revalidate: 60 } })
client.fetch(query, { }, {}, { next: { revalidate: 60 } })
you could tag the data with
client.fetch() if you just want to revalidate some dataexport const revalidate = 15 will revalidate the whole pageDwarf Crocodile
Ok, so one client.fetch() revalidate is best if I want to only do it on some data and not the whole page
And what's the purpose of the webhook?
@Dwarf Crocodile And what's the purpose of the webhook?
for revalidation when you update the data on sanity
instead of waiting for 15 sec
Dwarf Crocodile
Ah ok so it would be instant
yeah
Dwarf Crocodile
Ok, let me get it working the most basic way then I will make it more specialized and report back.
I really appreciate you guys. This has been driving me crazy
@Dwarf Crocodile I really appreciate you guys. This has been driving me crazy
no prob, take a look on their example
@Ray no prob, take a look on their example
Dwarf Crocodile
btw if I do
export const revalidate = xx on my app.tsx, does it propagate down to other components? For example my page.tsx contains BlogCards.tsx which fetches the blog posts, will this also revalidate based on this variable or would I have to export the variable on the BlogCards component as well.@Ray do you mean `page.tsx`? yes
Dwarf Crocodile
yeah
only export const revalidate on page.tsx tho
Northeast Congo Lion
Can you not fetch blog posts at page level? Instead of component level
Dwarf Crocodile
I can, and then pass them down to the BlogCards I suppose
Northeast Congo Lion
That’s how I do it with blogs. ISG and then pass them down
Which means blogs instantly available
Dwarf Crocodile
What does ISG mean, sorry?
Northeast Congo Lion
Incremental static generation
Which means page is revalidated
Idk if that’s still the term these days but it was back in early next.
I would fetch on the component with
https://nextjs.org/docs/app/building-your-application/data-fetching/patterns#fetching-data-where-its-needed
client.fetch since its encouraged way to fetch data from the dochttps://nextjs.org/docs/app/building-your-application/data-fetching/patterns#fetching-data-where-its-needed
Dwarf Crocodile
Instead of page?
yes if you have multiple block of component
Donskoy
I'm curious if you know how cache works under the hood, what I mean, if we were to use slug as a cache tag, would that mean only a single post with that slug would be reloaded when we call revalidateTag?
Northeast Congo Lion
Would fetching on client not give a small flash of the blog ray?
As he will fetch from useeffect right? So initial blog list prop will be empty, then useffect populates in fetch
Northeast Congo Lion
Idk I just assumed lol
@Ray yes
Donskoy
And consequently, if we were to use the same tag for every post, the cached values would override each other? If that is right, we can pass in two tags, one general for all posts and the other specific for a single post, e.g. tag: ['posts', slug]?
Northeast Congo Lion
Incase he has filtering etc on blog list
@Ray OP is fetching with useEffect?
Dwarf Crocodile
no here's how I fetch on the component btw:
import Image from 'next/image';
import Link from 'next/link';
import { getInsights } from '@/sanity/utils';
import { timeAgo } from '@/app/helpers/time';
const BlogCards = async () => {
const insights = await getInsights();
return (
<div className='grid md:grid-cols-2 lg:grid-cols-3 gap-16 md:gap-6 lg:gap-8'>
{insights.map((insight) => (
<Link
key={insight._id}
href={`/insights/${insight.slug}`}
className='w-full flex flex-col space-y-4 hover:scale-[1.01] transition-transform hover:no-underline'
>
<div className='relative bg-red-100 h-40'>
{insight.cover && (
<Image
src={insight.cover}
alt={insight.coverAlt || 'cover'}
fill
sizes='100vw'
className='object-cover'
/>
)}
</div>
<div className=''>
<h3>{insight.title}</h3>
<div className='text-xs text-darkText'>
{timeAgo(insight._createdAt)}
</div>
<p className='py-4'>{insight.excerpt}</p>
<div className=''>continue reading...</div>
</div>
</Link>
))}
</div>
);
};
export default BlogCards;@Ray correct, that's why the tag is an array
Donskoy
Thanks very much! One more follow up question: what happens if a slug is just a number, would cache get overriden if we were to use the same number in combination with another resource, let's say a user like so tag: ['users', userId]? What I mean, if I now have a user with id=1 and a post with slug=1, will their caches override each other, and if not, since revalidateTag only takes in a single tag, calling revalidateTag(1), would both of the cached values get purged from cache?
@Ray make it something like this `posts-id-1`, `users-id-1`
Donskoy
Thank you very much sir, you helped a lot!
otherwise it will revalidate for both post and user
Dwarf Crocodile
@Ray and @Northeast Congo Lion seriously thank you all so much. I was in touch with sanity support and all they managed to do was ask me if I updated my env variables and my coors settings... The equivalent of asking me if I tried restarting my modem.
This really helped and I actually understand the problem and solution too wich is a big plus.
@Dwarf Crocodile <@743561772069421169> and <@213063998843781120> seriously thank you all so much. I was in touch with sanity support and all they managed to do was ask me if I updated my env variables and my coors settings... The equivalent of asking me if I tried restarting my modem.
Northeast Congo Lion
You got it working?
@Dwarf Crocodile <@743561772069421169> and <@213063998843781120> seriously thank you all so much. I was in touch with sanity support and all they managed to do was ask me if I updated my env variables and my coors settings... The equivalent of asking me if I tried restarting my modem.
lol, have you told them you are using nextjs
@Northeast Congo Lion You got it working?
Dwarf Crocodile
yeah! at least partially. But I think from here I can use what we used here and apply to the other components. Might even write the webhook so it's a more permanent solution.
@Ray lol, have you told them you are using nextjs
Dwarf Crocodile
yeah dude I lead with that haha
oh well they should at least link their repo of the next example
Dwarf Crocodile
yeah this code you sent is super helpful