1
00:00:03,000 --> 00:00:05,607
We set up a Strapi instance, with

2
00:00:05,607 --> 00:00:07,898
25 reviews already available.

3
00:00:07,977 --> 00:00:10,422
And by the way, I still have the Strapi

4
00:00:10,422 --> 00:00:12,241
server running in a Terminal.

5
00:00:12,304 --> 00:00:15,752
We'll always need the CMS running from now on.

6
00:00:15,752 --> 00:00:19,240
Now, let's go back to our Indie Gamer website.

7
00:00:19,240 --> 00:00:22,660
We want to modify our Next.js application

8
00:00:22,660 --> 00:00:25,581
to fetch the data from the CMS API.

9
00:00:25,664 --> 00:00:28,407
Maybe we can start from the Reviews page,

10
00:00:28,407 --> 00:00:30,188
since that's where we display

11
00:00:30,188 --> 00:00:31,907
a list with all the reviews.

12
00:00:31,968 --> 00:00:34,622
So let's switch to Visual Studio Code,

13
00:00:34,622 --> 00:00:36,968
and note that I'm running the "next

14
00:00:36,968 --> 00:00:38,912
dev" server in this terminal.

15
00:00:38,979 --> 00:00:42,506
So we have two servers running on our machine:

16
00:00:42,506 --> 00:00:45,029
Next.js on port 3000,

17
00:00:45,029 --> 00:00:48,525
and Strapi on port 1337.

18
00:00:48,525 --> 00:00:50,269
Now let's go and open the

19
00:00:50,269 --> 00:00:52,013
code for the ReviewsPage.

20
00:00:52,083 --> 00:00:55,097
As a reminder, here we call "getReviews"

21
00:00:55,097 --> 00:00:56,303
to get the data.

22
00:00:56,379 --> 00:00:59,494
And this function loads it from local files.

23
00:00:59,494 --> 00:01:01,783
First it calls "getSlugs",

24
00:01:01,783 --> 00:01:03,823
that lists the files in the

25
00:01:03,823 --> 00:01:05,711
"content/reviews" folder.

26
00:01:05,787 --> 00:01:08,552
And then for each "slug" we call "getReview",

27
00:01:08,552 --> 00:01:10,717
that reads the Markdown file.

28
00:01:10,717 --> 00:01:14,191
So, what we'll do over the next few videos is

29
00:01:14,191 --> 00:01:16,927
change all that code to fetch the

30
00:01:16,927 --> 00:01:19,414
data from the CMS API instead.

31
00:01:19,497 --> 00:01:22,067
As we've seen, we can get the reviews

32
00:01:22,067 --> 00:01:24,499
by sending a request like this one.

33
00:01:24,569 --> 00:01:26,991
And to make an HTTP request in our

34
00:01:26,991 --> 00:01:29,412
JavaScript code we can use "Fetch"

35
00:01:29,484 --> 00:01:31,834
that is a global function available

36
00:01:31,834 --> 00:01:33,110
both in the browser

37
00:01:33,177 --> 00:01:36,116
and in the latest Node.js version.

38
00:01:36,116 --> 00:01:38,043
The way it works is pretty simple:

39
00:01:38,043 --> 00:01:40,398
you call "fetch" passing the URL,

40
00:01:40,398 --> 00:01:42,406
and this returns a "response"

41
00:01:42,406 --> 00:01:44,068
object (asynchronously),

42
00:01:44,138 --> 00:01:46,879
then you can get the data in the response

43
00:01:46,879 --> 00:01:49,152
body by calling the "json" method,

44
00:01:49,219 --> 00:01:50,975
that's also asynchronous.

45
00:01:50,975 --> 00:01:52,852
So, let's go and write some

46
00:01:52,852 --> 00:01:54,660
code to fetch the reviews,

47
00:01:54,729 --> 00:01:57,009
by calling the Strapi API.

48
00:01:57,009 --> 00:01:59,953
Now, before we modify our existing code,

49
00:01:59,953 --> 00:02:02,162
I'd like to start by testing

50
00:02:02,162 --> 00:02:04,371
the API requests separately.

51
00:02:04,450 --> 00:02:06,222
To do that I'll create a new

52
00:02:06,222 --> 00:02:07,742
folder called "scripts",

53
00:02:07,805 --> 00:02:09,997
where we'll write some files that

54
00:02:09,997 --> 00:02:11,590
we can execute directly,

55
00:02:11,657 --> 00:02:13,565
without having to run the

56
00:02:13,565 --> 00:02:15,473
full Next.js application.

57
00:02:15,550 --> 00:02:20,355
Let's create a file called "strapi-request.mjs".

58
00:02:20,355 --> 00:02:23,677
Note that I'm using the "mjs" extension

59
00:02:23,677 --> 00:02:26,741
to tell Node.js to enable ES modules

60
00:02:26,741 --> 00:02:28,699
when running this file.

61
00:02:28,784 --> 00:02:30,991
This means we can use features

62
00:02:30,991 --> 00:02:32,903
like the "import" keyword.

63
00:02:32,977 --> 00:02:34,922
Anyway, here we want to call

64
00:02:34,922 --> 00:02:36,797
the URL to get the entries,

65
00:02:36,866 --> 00:02:39,719
but we don't have "restaurants", but "reviews".

66
00:02:39,879 --> 00:02:42,516
We can get a "response" by awaiting

67
00:02:42,516 --> 00:02:43,872
a call to "fetch",

68
00:02:43,947 --> 00:02:46,432
that's available as a global function,

69
00:02:46,432 --> 00:02:49,178
and we just need to pass it the "url".

70
00:02:49,178 --> 00:02:51,601
Next, we can get the response body

71
00:02:51,601 --> 00:02:53,667
by calling the "json" method,

72
00:02:53,738 --> 00:02:56,122
that we also need to "await" because

73
00:02:56,122 --> 00:02:57,513
it returns a Promise.

74
00:02:57,579 --> 00:03:01,032
At this point let's simply log this "body" object,

75
00:03:01,032 --> 00:03:02,395
to see what we get.

76
00:03:02,395 --> 00:03:05,251
In the Terminal, I'll stop the dev server,

77
00:03:05,251 --> 00:03:07,239
and run our "strapi-request"

78
00:03:07,239 --> 00:03:09,226
script directly with "node".

79
00:03:09,297 --> 00:03:10,766
You can see that it worked.

80
00:03:11,010 --> 00:03:13,771
Our code called the CMS API,

81
00:03:13,771 --> 00:03:16,026
and received a response, that

82
00:03:16,026 --> 00:03:17,892
contains a "data" array.

83
00:03:17,970 --> 00:03:20,206
Each element is an object with

84
00:03:20,206 --> 00:03:22,442
an "id" and some "attributes".

85
00:03:22,516 --> 00:03:24,410
However, we cannot really see

86
00:03:24,410 --> 00:03:26,108
what the "attributes" are,

87
00:03:26,174 --> 00:03:28,912
it only shows that they're Objects.

88
00:03:28,912 --> 00:03:32,318
So maybe we could convert the "body" back to JSON,

89
00:03:32,318 --> 00:03:33,886
by calling "stringify",

90
00:03:33,954 --> 00:03:36,642
but formatting it nicely by setting

91
00:03:36,642 --> 00:03:38,562
2 spaces for indentation.

92
00:03:38,639 --> 00:03:41,723
The third argument to "stringify" is the amount

93
00:03:41,723 --> 00:03:43,953
of "space" to use for indentation.

94
00:03:44,019 --> 00:03:45,756
While the second argument

95
00:03:45,756 --> 00:03:47,493
is a "replacer" function,

96
00:03:47,562 --> 00:03:49,850
but we don't need it, so we simply

97
00:03:49,850 --> 00:03:51,936
pass "null" in second position.

98
00:03:52,004 --> 00:03:54,527
This way, if we run our script again,

99
00:03:54,527 --> 00:03:56,636
we can now see the full data.

100
00:03:57,058 --> 00:04:00,233
In fact, maybe there's too much data now.

101
00:04:00,233 --> 00:04:01,992
We can see some attributes

102
00:04:01,992 --> 00:04:03,616
like "slug" and "title",

103
00:04:03,684 --> 00:04:06,746
but then the "body" for each review is so big

104
00:04:06,746 --> 00:04:09,238
that it's difficult to see anything else.

105
00:04:09,238 --> 00:04:11,415
What we could do is write the

106
00:04:11,415 --> 00:04:13,442
response to a file instead.

107
00:04:13,517 --> 00:04:15,966
Let's import a function to do that

108
00:04:15,966 --> 00:04:17,838
from the "node:fs" module.

109
00:04:18,077 --> 00:04:21,103
For this script we can use "writeFileSync"

110
00:04:21,103 --> 00:04:22,185
that's simpler.

111
00:04:22,257 --> 00:04:24,357
No need to use asynchronous

112
00:04:24,357 --> 00:04:26,379
code for this manual test.

113
00:04:26,457 --> 00:04:28,501
Here we want to write a "file", in

114
00:04:28,501 --> 00:04:30,365
the same folder as this script,

115
00:04:30,425 --> 00:04:33,535
let's call it "strapi-response.json".

116
00:04:33,587 --> 00:04:35,916
Then we can call "writeFileSync"

117
00:04:35,916 --> 00:04:37,589
passing that file name,

118
00:04:37,662 --> 00:04:40,944
and the second argument will be the data to write.

119
00:04:40,944 --> 00:04:44,008
Now, we want to save the formatted JSON

120
00:04:44,008 --> 00:04:46,335
so let's assign this to a variable,

121
00:04:46,335 --> 00:04:48,064
let's call it "formatted",

122
00:04:48,130 --> 00:04:51,160
and this is what we want to write into the file.

123
00:04:51,160 --> 00:04:53,701
As third argument we need to specify

124
00:04:53,701 --> 00:04:55,324
the character encoding,

125
00:04:55,395 --> 00:04:57,579
that must be "utf8".

126
00:04:57,579 --> 00:04:59,227
Let's see if this works, if

127
00:04:59,227 --> 00:05:00,692
we run the script again.

128
00:05:00,753 --> 00:05:03,441
You can see that it created a file

129
00:05:03,441 --> 00:05:05,812
called "strapi-response.json",

130
00:05:05,891 --> 00:05:07,916
and this way we can more easily

131
00:05:07,916 --> 00:05:09,681
see the data in the editor.

132
00:05:09,746 --> 00:05:12,491
We have a separate object for each review,

133
00:05:12,491 --> 00:05:15,377
with attributes like "slug", "title",

134
00:05:15,377 --> 00:05:16,782
"body", and so on.

135
00:05:16,860 --> 00:05:20,265
And these are all inside an array called "data".

136
00:05:20,265 --> 00:05:22,426
There's also some other information,

137
00:05:22,426 --> 00:05:23,567
about "pagination",

138
00:05:23,627 --> 00:05:25,746
in an object called "meta".

139
00:05:25,746 --> 00:05:28,514
We'll cover pagination in another section.

140
00:05:28,514 --> 00:05:30,852
Now, one thing to notice is that

141
00:05:30,852 --> 00:05:32,901
we don't have any information

142
00:05:32,901 --> 00:05:34,526
about the "image" here.

143
00:05:34,597 --> 00:05:36,591
As we've seen, in the CMS there

144
00:05:36,591 --> 00:05:38,392
is an image for each review.

145
00:05:38,456 --> 00:05:40,959
If we look at the first entry for example,

146
00:05:40,959 --> 00:05:42,996
there is an "image" field here,

147
00:05:42,996 --> 00:05:45,310
with a picture for this game.

148
00:05:45,310 --> 00:05:47,876
So why is it that we don't see

149
00:05:47,876 --> 00:05:49,844
it in the API response?

150
00:05:49,929 --> 00:05:52,384
The reason is that we need to tell

151
00:05:52,384 --> 00:05:54,694
Strapi which fields to populate.

152
00:05:54,767 --> 00:05:59,227
By default, the API "does not populate any relations,

153
00:05:59,227 --> 00:06:01,416
media fields" and similar.

154
00:06:01,500 --> 00:06:05,036
An image in the CMS is like a separate object,

155
00:06:05,036 --> 00:06:07,746
that's associated with a Review entry.

156
00:06:07,746 --> 00:06:10,569
By default, the API does not include

157
00:06:10,569 --> 00:06:12,530
any associated relations.

158
00:06:12,608 --> 00:06:15,297
If we do want them, we can pass

159
00:06:15,297 --> 00:06:17,726
"populate=*" as a parameter.

160
00:06:17,813 --> 00:06:19,898
Let's try this in our code.

161
00:06:19,898 --> 00:06:21,986
I'll keep the response on the right,

162
00:06:21,986 --> 00:06:23,945
so we can see both request

163
00:06:23,945 --> 00:06:25,903
and response side by side.

164
00:06:25,978 --> 00:06:28,551
Now, we want to append the "populate"

165
00:06:28,551 --> 00:06:30,150
parameter to the "url".

166
00:06:30,219 --> 00:06:32,573
And if we try running the script again,

167
00:06:32,799 --> 00:06:34,985
you can see that the response now

168
00:06:34,985 --> 00:06:36,972
includes an "image" attribute.

169
00:06:37,039 --> 00:06:41,152
"image" is an object that has its own "data" property,

170
00:06:41,152 --> 00:06:43,209
with "id" and "attributes".

171
00:06:43,285 --> 00:06:45,263
And there are lots of attributes,

172
00:06:45,263 --> 00:06:47,061
including different "formats".

173
00:06:47,121 --> 00:06:49,758
Strapi automatically makes each image

174
00:06:49,758 --> 00:06:51,825
available in different sizes,

175
00:06:51,896 --> 00:06:54,542
like "large", "medium", and "small".

176
00:06:54,542 --> 00:06:56,951
But all we need for our application

177
00:06:56,951 --> 00:06:58,671
is really the full "url",

178
00:06:58,740 --> 00:07:00,513
that's visible down here.

179
00:07:00,513 --> 00:07:03,169
Anyway, we now have all the information

180
00:07:03,169 --> 00:07:04,939
about the "image" as well,

181
00:07:05,008 --> 00:07:07,632
by passing the "populate" parameter.

182
00:07:07,632 --> 00:07:09,884
In the next video we'll see how to

183
00:07:09,884 --> 00:07:11,937
select only the fields we need,

184
00:07:12,004 --> 00:07:13,879
rather than fetching everything

185
00:07:13,879 --> 00:07:15,511
like we're doing right now.

