So now that we're getting our news
from the database,
I wanna migrate the entire NextJS application
to only use that database,
and not use that dummy-news file here.
Therefore, I'll actually delete that file,
and attached, you find an updated news.js file,
which now gives you a bunch of functions
that reach out to the database
and get the data from there.
Most of these functions, but not all of them,
also have that delay added to them
so that we simulate a slower database.
And I'll start by migrating this slug page,
so the NewsDetailPage which we got here.
In there, I'm currently still trying
to reach out to the dummy-news,
and of course, that won't work
because I removed that file.
Instead, we can now get our newsItem
by calling the getNewsItem function,
which is imported from this updated news.js file.
And this function wants the slug as an input
and then returns a promise with that news data.
Now, we have the slug here,
but, of course, since we get back a promise,
I wanna await this.
And in order to use await, we need to add async here,
which we can add because this is a React server component.
We got no use client directive at the top.
Now, that should actually be all that we need to do.
That should be all that's required
in order to use this function
to fetch the newsItem from the database.
If I save that, and I reload the /news page,
and I click on such a news item,
I do see that loading fallback again
and then the news details here.
And we see that loading fallback
because we have that loading.js file here.
And as I mentioned before,
that will become active, you could say,
whenever you are waiting for a component
to return its content, to render its content.
So whenever you're waiting
for a component's promise to resolve,
if it's a component that's in a sibling page.js file
or some nested page.js file below the loading.js file.
So here since slug is a nested route of the news route
and the loading.js file is stored in the news folder,
this nested NewsDetailPage
will also use this loading.js file for its fallback.
If we wanted to have a more specific loading fallback,
we could, of course, also add a nested loading.js file here
next to the page.js file.
There, we can, of course,
then also export a component function,
LoadingNewsItem(), whatever,
and then return a more specific text
or something like this,
like loading news item...
And now it would be this fallback that's shown
whilst we're waiting for those news details.
So if I reload this news page,
wait for the news and click on such a item,
now I see that more specific fallback text.
So that's also something you can do.
Now, of course, I also have the nested image route here
and there I also get my newsItem.
So it's the same logic here.
We wanna remove the dummy-news import
and decorate this component with async.
And then, we can get the news item
by awaiting getNewsItem
and pass the newsItemSlug to this function
and we're good to go.
And again, we could add
a more specific nested loading.js file here
to have a more specific loading fallback.
But here I'm fine with the parent one.
So the one that is defined one folder
above this page.js file.
So that should work.
And of course, I also wanna update
this interceptor route here, this one.
And there we now have a problem
because here I'm now using use client.
And as you learned,
we can only use async await on a component
if it's not a client component.
And therefore, migrating this component
might've been a bit trickier
than the other pages and components.
But in order to migrate it,
we should take a closer look at it
and understand why it must be a client component.
And here it must be a client component
because I'm using useRouter
and I need that for my backdrop
so that clicking on the backdrop takes us back
to the page we came from.
So one thing we can do here in order to get rid
of use client here is make this div,
which uses the router a separate component,
which we then use inside of this page component.
That way that page component
can become a server component again,
and we can use async wait.
It's essentially a similar approach we took way earlier
in the course when we outsourced the NavLink
into its own component so that that was a client component
and the header could stay a server component.
Now I'll do the same thing here with my modal backdrop.
Therefore, I'll add a new component
in the components folder and I'll name it modal-backdrop.js
and in there export my ModalBackdrop component function
and add use client at the top here
because I know I'll need it
because I wanna use useRouter from next navigation
and then return that backdrop from that page.js file.
So this div here, I'll cut it
and move that into my modal-backdrop.js file.
And then in the page.js file,
I'll use the ModalBackdrop here.
That way we can now actually remove
the useRouter usage here, remove this import
and remove the use client directive.
And now we can again add async here
because now we have a React Server component again
and remove the dummy-news import
and instead get our newsItem here
by calling getNewsItem
and passing this newsItemSlug to it.
And of course, by adding await here.
And that way we should be good to go again.
If I now click on that image, it's intercepted,
and then I see this modal.
Now, of course, we see
that loading news item folder here temporarily
until this is loaded but that's not necessarily bad
because again, it tells us that something's happening.
Now, one thing you might encounter here,
if you then reload this interceptor page
is that you then get a not found error.
And we get this not found error
because no default component was found for a parallel route.
And this error can
and should be fixed by renaming this page.js file,
which is in the @modal folder here to default.js.
With that, if you then also restart the development server
and you then reload this page, you'll see
that now the image is loaded in full screen mode.
So with that, we did now finish the news-related part here,
and we also saw how we can fix this problem
of having a client component in a place
where we don't want one
by outsourcing the client-dependent code
into a smaller child component.
And by therefore turning the overall bigger page component
into a server component again.
Now with that, we can move
to the archive part here
and there maybe start with the latest page,
the default page here.
In there, I'm calling getLatestNews, and that's fine.
We can continue using this function,
but it's now an async function
with an arbitrary delay in there.
So again, we should use async await here
and that would be all.
However, it might also be nice to show some loading fallback
and therefore here next to this layout.js file,
I'll add a loading.js file
and export my function, which I'll call ArchiveLoading
and return some loading fallback content.
Now, we should also go to the other parallel route,
this filter route here and this page.js file.
And of course, here again,
we wanna continue using all these functions,
which I am already using,
but most of these functions are now async functions.
This one actually isn't,
but most of the other functions are, for example,
also the getAvailableNewsYears function is one.
Therefore, we again should add async here in front
of this function keyword
and then await this, await this.
This function then actually doesn't return a promise,
so we don't need await here,
but we will need it again here for getNewsForYearAndMonth.
And that again should be all.
It's really straightforward,
though here I'm actually also using these functions.
So again, there we should also await this.
And actually, I'll therefore outsource this
and get my availableYears here
by awaiting getAvailableYears
so that I keep my if statement lean and simple.
And then this here doesn't return a promise.
So we can keep it here.
We could also outsource it into a separate constant
or variable, but I'll just keep that code as it is.
But that should then be all.
And if we now save that
and we go to the archive area,
we see that loading fallback here
and then the different data pops in,
as you can tell.
However, as I try to load the data for a year,
it doesn't seem like anything's happening initially.
And then after a short while, I get an error
that we have an invalid filter
and we're getting this error here
because of this if check here.
In there, I am converting the selectedYear
and selectedMonth to numbers,
and I'm then checking whether the availableYears
or the availableMonths include that number in that array.
And previously with the old code where I used
that dummy-news array, that code was correct.
But now where we're fetching data from the database,
the availableYears and also the availableMonths
will all be string values.
And therefore, checking whether these arrays
of strings include some numbers will fail.
The solution therefore simply is to get rid
of these plus signs here
to not convert these values from strings to numbers.
And with that, we should be good to go.
If we now reload here, we see the loading fallback.
And then after a while, I see the articles
for the selected year.
And then once I click on a month, also eventually,
the ones for a selected month.
Though, of course, that takes a while to load
and we got no feedback whilst we're waiting.
I click on 05 and then nothing happens.
And only after a while do we see the article for that month.
So that is something we should improve and we will improve.
But what's important to take away here
is that we did now migrate the entire application
to use that local database
and show loading fallbacks whilst we're waiting
for the data, and that we therefore now improve
this NextJS application and made it a bit more realistic.