So here on this slug page, on this catch all page,
we're currently getting the concrete path values
from the router,
to then get the year and the month
and fetch the appropriate events for us here.
Now the question is, how do we wanna do that in the future
with our newly gained knowledge?
And we have a couple of options here.
We can use getStaticProps to pre-generate this.
But of course, for the filtered events,
we'll have a lot of different combinations of parameters.
2021, and one, and five, and two, and so on.
That's not necessarily an issue, though,
because we will have to use getStaticPaths anyways,
and once we add that, we could only pre-render a couple
of those combinations, and not all of them.
And instead, then, use fallback set to true or blocking.
But how should we decide
which paths should be pre-generated?
In the end, all possible filters are equally likely
to be visited.
So, I would have a hard time picking a couple
of combinations that should be pre-generated.
And pre-generating all possible combinations
is also not a great option
because that could be a lot of pages.
Especially if we have no year restriction, for example.
So, getStaticProps might not be ideal here.
Maybe, here, getServerSideProps is better.
So that we do indeed fetch the data on the fly
for every incoming request, and we then return the page
for every incoming request.
So let's start with that.
In this slug page, I will export an async function
called getServerSideProps.
You know that here we get the context.
And then here we wanna return an object
which is similar to the object we return in getStaticProps.
With the props key and possibly also with the not found key
and the redirect key if we need it.
Now here, from the context, we can get access to the params.
So here, we can get access to the parameters
for which this page was visited.
And that's good because now,
we basically wanna repeat what we previously did
in our component function.
We wanna get our year and month,
and convert that to a number,
and then validate it,
and then ultimately get our filtered events.
So I will copy all that code,
though we're going to edit it a bit,
but I'll copy all that code,
and bring it down there into getServerSideProps.
Now here, we're accessing filtered data
that should actually be our params.
Because up there, filtered data is also just what we read
from the router query, which are also our params
when accessed through useRouter.
So therefore here I'll rebuild filterData
and access params.slug.
So we still access .slug
because that is our catch-all grouping parameter name,
if you wanna call it like that.
And that will still be an array with multiple values,
and we are interested in the first two values
which should be the year and the month.
Which is why we convert them to numbers
and then validate them down there.
Now if validation fails, however, we don't wanna return JSX.
That's not possible in getServerSideProps.
We always have to return an object instead.
But if the validation fails,
I don't wanna return a props object here,
or a props key.
Instead, here, I'll then set notFound to true.
I wanna show the 404 page
if an invalid parameter combination is passed in.
We could also consider redirecting to some error page
if we had one.
But here, we don't have one.
We could add one, but I will not do that here.
So I'll comment this out,
and instead show the 404 error page.
Another alternative would be to set some props
like the hasError prop,
and then handle this specific prop
in our component function to show an error message.
And actually,
since we do have that error specific JSX code here,
that might actually be the best alternative.
So it's still worth knowing the other ones,
but I will now not show the 404 page,
but instead return my special hasError prop,
set to true if the validation fails.
So that in the component function,
in this FilteredEventsPage function,
we should expect props, and then down there,
instead of validating our query parameters,
I check if props hasError is true.
And if that's the case, I'll show this error message.
I think that actually makes the most sense,
but you can also go
with one of the two alternatives I showed.
Now if we make it past this if check,
we do have valid parameter values,
and therefore now we wanna get our filtered events.
For this, I'll go to dummy data,
and take this getFilteredEvents function,
and bring that over into api-util.
Maybe down there.
Here, we getFilteredEvents by reaching out to DUMMY_EVENTS
and calling filter on that.
Now just as in the other functions here,
I will instead now turn this into a async function,
then get access to allEvents by awaiting getAllEvents,
and then using allEvents here
instead of DUMMY_EVENTS for filtering.
And with that, back in this slug page,
we now wanna import getFilteredEvents,
not from dummy-data, but from the helpers folder,
and the api-util file.
And then down there in getServerSideProps,
we now get our filtered events
by awaiting getFilteredEvents,
to which we still pass this object with this data.
Because I haven't changed the function's signature
of this function.
It still wants the same parameter.
But we should await because this is now an async function
returning a promise, therefore.
So that gives us our filteredEvents,
and hence, here, through props, we can expose our events,
our filtered events,
through an events prop.
And therefore, back in the component function,
now, in there,
we actually don't really need to parse the URL anymore,
though I'll keep that code around for now.
But I will comment it out like this.
Instead, now we are already using props.hasError,
and I now also in addition wanna set my filteredEvents here
equal to props.events.
So this events prop which we populate in getServerSideProps.
With that, if we save this,
if I reload this page for this kind of filter,
I still get no events found.
Now, if I do pick a combination that exists, though,
I get an error: numYear is not defined.
That makes sense, because now,
in there, I am constructing a date
with numYear and numMonth,
and we're not having that anymore,
because I am not extracting it from the URL anymore.
Now we could do that,
but since we do get it in getServerSideProps anyways,
we can't just expose numYear and month
through props to the component.
So here, besides exposing the events,
I'll also expose my date,
and here I'll then just expose this as a object
where year is set equal to numYear,
and month is set equal to numMonth.
And now that we exposed this date prop,
we can go to the component function,
and build a date by accessing props.date.year,
and then props.date.month.
So these props which we just added.
For that, if we save this and reload,
now this gets loaded correctly.
And this is now pre-rendered on the fly on the server
for every incoming request.
Because we are using getServerSideProps here.
And of course, again, we can see that
if we inspect the page source,
there, the event data is part of that HTML content.
And again, if I use some other filter
where we don't find any events, we see that message.
And if I enter something invalid here,
we see the invalid filter page.
And that also is pre-rendered
as you can see here.
So that's how we can use getServerSideProps.