We've seen how to fetch the products
on the server side, using getStaticProps.
Now let's look at "Option 2",
that is fetching the data on the client side.
Let's load our "index-2" page.
We're working on separate pages
so we can then compare the various approaches.
And this page still shows
these hard-coded products
that we want to remove
and replace with the data coming from the CMS.
Now, in this case we want to fetch the data
when this component is mounted,
as you would do in a plain React app.
So first of all we need
a state variable called "products",
that we can create with the "useState" hook.
And as the initial value
we can pass an empty array.
Then we can call the "useEffect" hook
to execute a function as soon as
this component is mounted.
And we want to pass an empty array of dependencies
to make sure this function is only executed once.
Inside this function we want to
make the HTTP request to fetch the products.
So we should call this URL,
but we've already written a function to do that:
this module exports a "getProducts" function.
So we can simply call that same function
from our client side code.
Now, "getProducts" is async
so it returns a Promise.
Rather than using "await" this time
I'll simply call "then" on the Promise
and pass "setProducts" to update the state variable.
Just to be clear, this is the equivalent of
receiving the products
and passing them to "setProducts".
We can simply pass the "setProducts" function directly.
Anyway, this is how we can fetch the data
on the client side.
If we save these changes,
we'll see the "real" products
displayed on the page.
So the end result looks the same
as with our "Option 1".
But the way it works is a bit different.
Let me show the server logs as well.
When we load this page,
what happens is that
the page is pre-rendered on the server side,
but "products" is set to its initial value,
that is an empty array.
The HomePage component is
hydrated on the client side,
again with an empty array as products.
Then the "useEffect" hooks runs,
we fetch the data from the CMS,
and at that point the component is re-rendered
with an array of 6 elements as the "products".
This is how a typical client-side React app works.
Now, let's compare this
to the server side approach,
that is when we load our "index-1" page.
In this case, as we know,
the data is fetched in the "getStaticProps" function
so when the HomePage is
pre-rendered to HTML on the server
it already includes the real product data.
And then, as usual, the component is hydrated
on the client side, using the same props.
We can see that same difference more clearly
if we look at the network requests.
When we load the "index-1" page,
we know that the server returns the HTML document.
And if we look at the Response tab
we can see the full HTML.
Let's format it with "Pretty-print",
and here we can see how
the pre-rendered HTML already includes
all the products in the list.
We know from early in the course
that pre-rendering is one of
the main advantages of Next.js,
but here we're focusing on this particular data
that's rendered inside a list,
so it's just a part of the page.
If we do the same experiment with "index-2"
of course we'll see something different.
The HTML document will still have been
pre-rendered by the server,
but if we go and look for that same
"ul" element in the HTML
in this case the list is empty.
Because, as we've seen in the logs,
it was rendered with an empty array of products.
But then, when the browser executes
the JavaScript code for this page,
this will make an HTTP request to the CMS API.
We can see the URL here.
This is actually another important difference
compared to the server-side approach:
if we do the fetching on the client side
that means that our CMS API
needs to be accessible to the public,
because it will be called from the web browser
of anybody who visits our website.
While in the server-side approach,
the CMS API only needs to be accessible
from the server when we run our Next.js app.
In fact, if we build our site statically
the CMS only needs to be available at build time.
So that's another thing to keep in mind.
Now, if we look at the JSON response
since we're calling the CMS directly
we always load all the data returned by the CMS,
including many fields we don't need.
While if we fetch the data on the server side
we can keep only the fields we need
and return less data to the client.
So that's another potential advantage
of the server-side approach:
we can send less data to the client,
making our app slightly faster.
So based on what we've seen so far
it looks like fetching data on the server side
has quite a few advantages.
Our page can be fully pre-rendered to HTML,
which makes it faster to load,
and can also be useful for search engines.
We only need the CMS to be accessible
from the server where we run our Next.js app,
and not exposed to the whole world.
And we can also filter the data
before returning it to the client,
reducing its size.
But there is also a potential advantage
with the client side approach:
by fetching the data in the browser
directly from the CMS
we can be sure that the page will display
the latest data available.
If we take the server side approach
and generate all our pages statically
what happens if we change
the product data in the CMS?
Statically generated pages never change,
so our website would keep showing the old data.
This is potentially a big problem,
and we'll talk more about it in the next video.