We set up a Strapi instance, with
25 reviews already available.
And by the way, I still have the Strapi
server running in a Terminal.
We'll always need the CMS running from now on.
Now, let's go back to our Indie Gamer website.
We want to modify our Next.js application
to fetch the data from the CMS API.
Maybe we can start from the Reviews page,
since that's where we display
a list with all the reviews.
So let's switch to Visual Studio Code,
and note that I'm running the "next
dev" server in this terminal.
So we have two servers running on our machine:
Next.js on port 3000,
and Strapi on port 1337.
Now let's go and open the
code for the ReviewsPage.
As a reminder, here we call "getReviews"
to get the data.
And this function loads it from local files.
First it calls "getSlugs",
that lists the files in the
"content/reviews" folder.
And then for each "slug" we call "getReview",
that reads the Markdown file.
So, what we'll do over the next few videos is
change all that code to fetch the
data from the CMS API instead.
As we've seen, we can get the reviews
by sending a request like this one.
And to make an HTTP request in our
JavaScript code we can use "Fetch"
that is a global function available
both in the browser
and in the latest Node.js version.
The way it works is pretty simple:
you call "fetch" passing the URL,
and this returns a "response"
object (asynchronously),
then you can get the data in the response
body by calling the "json" method,
that's also asynchronous.
So, let's go and write some
code to fetch the reviews,
by calling the Strapi API.
Now, before we modify our existing code,
I'd like to start by testing
the API requests separately.
To do that I'll create a new
folder called "scripts",
where we'll write some files that
we can execute directly,
without having to run the
full Next.js application.
Let's create a file called "strapi-request.mjs".
Note that I'm using the "mjs" extension
to tell Node.js to enable ES modules
when running this file.
This means we can use features
like the "import" keyword.
Anyway, here we want to call
the URL to get the entries,
but we don't have "restaurants", but "reviews".
We can get a "response" by awaiting
a call to "fetch",
that's available as a global function,
and we just need to pass it the "url".
Next, we can get the response body
by calling the "json" method,
that we also need to "await" because
it returns a Promise.
At this point let's simply log this "body" object,
to see what we get.
In the Terminal, I'll stop the dev server,
and run our "strapi-request"
script directly with "node".
You can see that it worked.
Our code called the CMS API,
and received a response, that
contains a "data" array.
Each element is an object with
an "id" and some "attributes".
However, we cannot really see
what the "attributes" are,
it only shows that they're Objects.
So maybe we could convert the "body" back to JSON,
by calling "stringify",
but formatting it nicely by setting
2 spaces for indentation.
The third argument to "stringify" is the amount
of "space" to use for indentation.
While the second argument
is a "replacer" function,
but we don't need it, so we simply
pass "null" in second position.
This way, if we run our script again,
we can now see the full data.
In fact, maybe there's too much data now.
We can see some attributes
like "slug" and "title",
but then the "body" for each review is so big
that it's difficult to see anything else.
What we could do is write the
response to a file instead.
Let's import a function to do that
from the "node:fs" module.
For this script we can use "writeFileSync"
that's simpler.
No need to use asynchronous
code for this manual test.
Here we want to write a "file", in
the same folder as this script,
let's call it "strapi-response.json".
Then we can call "writeFileSync"
passing that file name,
and the second argument will be the data to write.
Now, we want to save the formatted JSON
so let's assign this to a variable,
let's call it "formatted",
and this is what we want to write into the file.
As third argument we need to specify
the character encoding,
that must be "utf8".
Let's see if this works, if
we run the script again.
You can see that it created a file
called "strapi-response.json",
and this way we can more easily
see the data in the editor.
We have a separate object for each review,
with attributes like "slug", "title",
"body", and so on.
And these are all inside an array called "data".
There's also some other information,
about "pagination",
in an object called "meta".
We'll cover pagination in another section.
Now, one thing to notice is that
we don't have any information
about the "image" here.
As we've seen, in the CMS there
is an image for each review.
If we look at the first entry for example,
there is an "image" field here,
with a picture for this game.
So why is it that we don't see
it in the API response?
The reason is that we need to tell
Strapi which fields to populate.
By default, the API "does not populate any relations,
media fields" and similar.
An image in the CMS is like a separate object,
that's associated with a Review entry.
By default, the API does not include
any associated relations.
If we do want them, we can pass
"populate=*" as a parameter.
Let's try this in our code.
I'll keep the response on the right,
so we can see both request
and response side by side.
Now, we want to append the "populate"
parameter to the "url".
And if we try running the script again,
you can see that the response now
includes an "image" attribute.
"image" is an object that has its own "data" property,
with "id" and "attributes".
And there are lots of attributes,
including different "formats".
Strapi automatically makes each image
available in different sizes,
like "large", "medium", and "small".
But all we need for our application
is really the full "url",
that's visible down here.
Anyway, we now have all the information
about the "image" as well,
by passing the "populate" parameter.
In the next video we'll see how to
select only the fields we need,
rather than fetching everything
like we're doing right now.