Updating issue
Answered
i_lost_to_loba_kreygasm posted this in #help-forum
I am facing issues with updating the DOM . If I insert a new document in the mongo Database,the network is fetching the updated documents but I don't see it in the DOM
Answered by B33fb0n3
perfect. As you can see: the relevant pages where the user can see your data are static. That means, that they will build once (during build time) and then just served. In dev mode, it will be nearly always dynamic, that's why it still works in dev mode.
So when you change data you also want to "rebuild" that specific page. You can do that by "revalidating" the data. And that works with a function from nextjs:
Call the function, when you want that your page should show new data.
Another thing you can do: revalidate that data after a specifc amount of time
-- Edit
Also it would be possible to make it dynamic like this: https://nextjs-forum.com/post/1311983350763749437#message-1312021790876373023
So when you change data you also want to "rebuild" that specific page. You can do that by "revalidating" the data. And that works with a function from nextjs:
revalidatePath("/your/path");Call the function, when you want that your page should show new data.
Another thing you can do: revalidate that data after a specifc amount of time
-- Edit
Also it would be possible to make it dynamic like this: https://nextjs-forum.com/post/1311983350763749437#message-1312021790876373023
46 Replies
@B33fb0n3 hi again
can you share some code? On how you insert the page, how you update the documents and how you load & show them
import db from "@/mongo";
export async function GET(req) {
const itemsCollection =await db.collection("items").find().toArray();
return Response.json({items:itemsCollection})
}this is the api route file
// App/page.js
async function Home() {
let { items, error, loading } = await getItems();
return <Container py={16} px={[4, 16, 16]} maxW={1260}>
<Box maxW={940} mx={'auto'}>
<Heading mb={8} fontSize={'4xl'}>Items</Heading>
<Flex mx={'auto'} justifyContent={'center'} gap={'20px'} wrap={'wrap'} >
{loading ? (
<p>Loading...</p>
) : error ? (
<p>{error}</p>
) : (
items.map((item, index) => (
<GreenCard
key={index}
name={item.name}
description={item.description}
price={item.price}
imageUrl={item.imageUrl}
/>
))
)}
</Flex>
</Box>
</Container>
}
export default Home;// this is the fetch helper file
export async function getItems(category){
let items=[];
let error=null;
let loading=false;
try{
loading=true;
const response = await fetch(`${process.env.NEXT_PUBLIC_URL}/api/get_items`);
if (!response.ok) {
throw new Error(`Failed to fetch data: ${response.status}`);
}
items = await response.json();
items=category?items.items.filter(item => item.category===category):items.items;
loading=false;
}
catch(err){
error=err.message;
}
return {items,error,loading}
}it works fine when I push the code for deployment
I am updating the mongo DB from the website
here is the deployed link if you wanna check the network tab
Inside your
Remove the "loading" part for a moment. Tell me when done
page.js can you replace the await getItems() with:await db.collection("items").find().toArray()Remove the "loading" part for a moment. Tell me when done
not working 😦
i wonder if its because I am using server component
@i_lost_to_loba_kreygasm done
great. It works like expected, correct? If yes, you can clearly delete everything that you used as wrappers (router handler & the function), because in SSR you don't need it (as you can see).
The page itself is SSR (server side rendered). So the server calculates everything first and then send this data to the client (so no loading inside your function needed as well). And when you now change something inside your database, the server won't notice.
So a page reload is needed to show the new data.
or
You can fetch the data clientside using a clientside fetching library like SWR or react query. With that you can refetch the data in an interval or when the page is refocused or ...
Why it works in dev mode? In dev mode the page automatically refreshes in the background (fast refresh)
The page itself is SSR (server side rendered). So the server calculates everything first and then send this data to the client (so no loading inside your function needed as well). And when you now change something inside your database, the server won't notice.
So a page reload is needed to show the new data.
or
You can fetch the data clientside using a clientside fetching library like SWR or react query. With that you can refetch the data in an interval or when the page is refocused or ...
Why it works in dev mode? In dev mode the page automatically refreshes in the background (fast refresh)
but refreshing page doesnt work
btw the page is fetching the updated documents if I go to the Network tab but I don't simply see it in the DOM
ok , so the data from the DB is fetched on server side once during deployment , is that why ?
when you build your page (
next build) which icon has the specific page? Static, Dynamic, ...?@i_lost_to_loba_kreygasm i hope these logs help u
that looks good, but I need the logs at the end. It looks more like this (of course with your routes):
@i_lost_to_loba_kreygasm need more ?
perfect. As you can see: the relevant pages where the user can see your data are static. That means, that they will build once (during build time) and then just served. In dev mode, it will be nearly always dynamic, that's why it still works in dev mode.
So when you change data you also want to "rebuild" that specific page. You can do that by "revalidating" the data. And that works with a function from nextjs:
Call the function, when you want that your page should show new data.
Another thing you can do: revalidate that data after a specifc amount of time
-- Edit
Also it would be possible to make it dynamic like this: https://nextjs-forum.com/post/1311983350763749437#message-1312021790876373023
So when you change data you also want to "rebuild" that specific page. You can do that by "revalidating" the data. And that works with a function from nextjs:
revalidatePath("/your/path");Call the function, when you want that your page should show new data.
Another thing you can do: revalidate that data after a specifc amount of time
-- Edit
Also it would be possible to make it dynamic like this: https://nextjs-forum.com/post/1311983350763749437#message-1312021790876373023
Answer
@i_lost_to_loba_kreygasm where do I use this function? 😔
you can use it only serverside and then where you like: in route handlers, server actions, (server components <-- technically possible, but I never had a use case), ...
@B33fb0n3 you can use it only serverside and then where you like: in route handlers, server actions, (server components <-- technically possible, but I never had a use case), ...
import { revalidatePath } from "next/cache";
import db from "@/mongo";
export async function GET(req) {
const itemsCollection =await db.collection("items").find().toArray();
revalidatePath('/')
return Response.json({items:itemsCollection})
} is this correct ? my home page is dependent on the data from the routeyeah i see it now
can the
revalidatePath function accept array ? since i have 4 pages dependent on the data@i_lost_to_loba_kreygasm js
import { revalidatePath } from "next/cache";
import db from "@/mongo";
export async function GET(req) {
const itemsCollection =await db.collection("items").find().toArray();
revalidatePath('/')
return Response.json({items:itemsCollection})
} is this correct ? my home page is dependent on the data from the route
no. You page right now should look like this:
We make it a bit easier. Add this on top:
Then it will work in production like it is in dev mode
// App/page.js
async function Home() {
let items = await db.collection("items").find().toArray();
return <Container py={16} px={[4, 16, 16]} maxW={1260}>
<Box maxW={940} mx={'auto'}>
<Heading mb={8} fontSize={'4xl'}>Items</Heading>
<Flex mx={'auto'} justifyContent={'center'} gap={'20px'} wrap={'wrap'} >
{
items.map((item, index) => (
<GreenCard
key={index}
name={item.name}
description={item.description}
price={item.price}
imageUrl={item.imageUrl}
/>
))
}
</Flex>
</Box>
</Container>
}
export default Home;We make it a bit easier. Add this on top:
// App/page.js
export const dynamic = 'force-dynamic'
async function Home() {
....
}Then it will work in production like it is in dev mode
ok , but what does
revalidatePath do ? so by revalidating , my pages are not built once on serverside during building?@i_lost_to_loba_kreygasm ok , but what does `revalidatePath` do ? so by revalidating , my pages are not built once on serverside during building?
imagine the building process (simplified): vercel now create html, css and js. When a user visits your page, vercel shows the created html, css and js. And that over and over again. Even if the data changed in the background, the html, css and js will stay the same.
With
With
revalidatePath vercel throws this html, css and js into the trash bin and creates a new version of your page. This new version will be served then over and over againso with
revalidatePath , the data is fetched over and over whenever there is a new request?@i_lost_to_loba_kreygasm so with `revalidatePath ` , the data is fetched over and over whenever there is a new request?
when you use it like you showed me, then yes.
However using
makes the route dynamic and like that is also refetches everytime someone visits the page
However using
export const dynamic = 'force-dynamic'makes the route dynamic and like that is also refetches everytime someone visits the page
i understand that the
dynamic refetches every timewhen you use it like you showed me, then yes. but wdym by this ?@i_lost_to_loba_kreygasm `when you use it like you showed me, then yes.` but wdym by this ?
you wanted to call it whenever you call your route handler. And that happens each page visit (with your old page.js)
so it does run over and over
i think i understand now
@i_lost_to_loba_kreygasm so it does run over and over
when you use it like you showed me, then yes
But you really should prefer the use of
Instead of revalidating each time. As your (old) page.js had a lot of irrelevant wrappers that are hard to maintain the use of this variables is recommended
export const dynamic = 'force-dynamic'Instead of revalidating each time. As your (old) page.js had a lot of irrelevant wrappers that are hard to maintain the use of this variables is recommended
sure thing