So now we did add static generation
and server side rendering to this mini application here.
What about client-side data fetching though?
Do we need that as well?
To be honest in this application,
I would argue that we don't really need it,
but we could still add it on a page
where I think that it would also be okay.
And that's this filter page,
there we are currently using getServerSideProps, that works,
but I think here client-side site data fetching
could also be okay.
By using that the page would load a bit quicker
because we don't need to pre-render it on the server,
but of course therefore the data would initially be missing.
So we need to show some loading state
until the data is there.
But I think this page would be a fine page
for a client-side data fetching,
because it might be nice to get to this page quickly.
And in addition, it's not that important for search engines.
I mean this filtered list of events,
that's not the main thing search engines should be crawling,
for them, the featured events, all events
and the event details are more relevant.
So therefore I think we could use
client-side data fetching here
on that filtered events page,
that does not mean
that you typically replace getServiceSideProps
with client-side data fetching.
It just happens to fit in quite well in this exact scenario.
Therefore, in this slug page,
I'll comment this code here back in,
because now for a client-side data fetching,
we again need access to the route parameters
inside of this component function
because that is where we are going to write
that data fetching code.
And we definitely, for example,
still need some loading state,
which should eventually be displayed.
Now I wanna do the data fetching with this useSWR hook,
which i showed you in the last course section.
So I'll quit the development server temporarily
and install the SWR package,
which brings us that hook,
and thereafter we can restart the development server.
Now here in the slug page,
we can import useSWR from this SWR package.
And then we can start using it.
Here after I got my filter data,
so after I got the route parameters,
I will call useSWR and then we wanna send a request
and I wanna send a request to firebase for filtered events.
Now again, we can add that filtering logic with firebase,
but since it's not the focus here,
I'll cheat and that will instead fetch all events
and then filter here in this component,
which is of course sub optimal,
but good enough for this example.
So therefore again, I'll grab this link,
which fetches all events
and use that as that key for useSWR.
And that then as you learned,
gives us back an object
where we get access to the fetched data,
and also to a possible error we might be getting.
Now, we also still need to transform the data though
that doesn't change.
This transformation still needs to be applied.
So therefore I'll copy that transformation logic,
and add it to this slug page with help of useEffect,
which we need to import from react.
And whilst we're there,
we can also already import useState
because we'll need that as well.
So now we're here after using useSWR,
I'll execute useEffect and pass an effect function to it.
And as a dependency, I'll add data
because this effect should rerun,
whenever the day that we fetched changes.
Then I'll check if we do have data,
because if we don't, there's nothing we need to do.
And if we do have data, I wanna transform it.
So I paste in my transformation logic
to transform the incoming data into such an events array.
However, that array should not be returned here,
instead it should be set as state,
so we can register some state here,
which is initially undefined.
The events state
with setEvents as a state updating function.
And then in here, I'll call setEvents
and set this equal to my events which I have here.
So to this events array, not events state,
in case this is confusing,
I can also name this loadedEvents and setLoadedEvents.
And then now they are setLoadedEvents
equal to the events array we're generating here.
Now, of course it's very possible
that we don't have any loadedEvents,
especially when this component is rendered
for the first time.
So before fetching data has even started.
So if we not have loadedEvents,
then I wanna show this loading output here.
Otherwise we make it past this if check,
and then in this case,
we get the filtered year and month we convert that
and we can then use that data to extract just events
which you wanna display here.
Again that is sub-optimal,
normally we would want to fetch just the right events,
but since this would be very firebase specific,
we're going to go with this approach here.
So therefore here, I then wanna use my filtering logic here
from inside the get filteredEvents function in api-util,
copy that over and add it here.
So that i have my filteredEvents here
and instead of all events, that's loadedEvents,
so this state we just added
that will then filter the events appropriately.
However here, I don't wanna compare this with year,
but with numYear and here with numMonth,
so with these two constants.
Now we've got the filtered events,
props.hasError will never be a thing
since we're not using server-side rendering anymore,
which is where this prop was coming from before.
Now we won't use it anymore, I'll soon remove it.
So that's no longer something we should check.
Instead here, I wanna bring back this if check,
which we outsourced to get server-side props.
Since we're moving back to client-side data fetching,
I'll bring it back onto the client-side.
So this is my if condition now,
like this,
and it might make sense to check this
before we try to filter, so I'll grab this code here
and actually check this here
before we derive the filtered events.
So if we make it past this check, we can filter for events.
We no longer need that line now.
And then we check if we, do we have filtered events?
Or to be precise, if we don't have filtered events,
in which case we show this fallback
and otherwise we still wanna display the filtered events.
And down there we can now again use numYear and numMonth
since I brought back those values here.
So with all of that,
we should be fetching the data on the client-side
with the useSWR hook.
Now here we might have an error.
So that's also something this error, this http error,
which we might be getting, which we should consider,
and I'll simply check here.
Or if we have an error, then I wanna show this error output.
Of course you could also handle it separately.
And with all that added,
we brought client-side data fetching back.
And that means of course,
that we should now remove getServiceSideProps.
Having both together, doesn't make a lot of sense.
It can make sense to have, getStaticProps
with client-side fetching
so that you have some pre-rendered page
and you then update it with client-side fetching,
but getServiceSideProps
and client-side fetching makes no sense
because getServiceSideProps is re-executed
for every request anyways.
So you are guaranteed to have the latest data there.
So if you use client-side data fetching,
as we are doing it here,
it makes no sense to use that
in conjunction with getServiceSideProps.
At least not if your concern is having up-to-date data.
it could make sense if you need to look into request headers
or anything like that,
but we're not doing that here, so we can comment this out.
And with all that, if we save all the code again,
if I reload this page here
for a filter where I have no events I see that,
if I enter something invalid, I see that.
And if I do a set of valid filter, I see that.
And if I reload, I see loading at that.
And of course, if we now inspect the page source,
this page is now missing the event data,
instead it only contains that loading text,
because when it was pre-rendered,
we didn't pre-fetch the data,
we didn't prepare the data for the pre rendering.
Since I commented out, getServiceSideProps
and therefore all Next.js saw
when it pre-rendered this page,
was in the end, this loading state this year,
because we don't have any loaded events
the first time this component is rendered by Next.js.
Now as explained using client-side data fetching,
is totally optional here.
There's nothing wrong with getServiceSideProps,
but now we also saw that in action again.
And therefore, hopefully it's now clear
how those different data fetching approaches work,
and when you might wanna consider using which.