1
00:00:03,000 --> 00:00:05,990
The ReviewPage is now a dynamic route,

2
00:00:05,990 --> 00:00:09,156
meaning that this same component will be used

3
00:00:09,156 --> 00:00:12,167
to render all the different review pages.

4
00:00:12,167 --> 00:00:13,956
This also means that, if we

5
00:00:13,956 --> 00:00:15,612
want to add a new review,

6
00:00:15,678 --> 00:00:19,096
we can now simply create a new Markdown file.

7
00:00:19,096 --> 00:00:22,487
Let's review the "hellblade" game for example.

8
00:00:22,487 --> 00:00:24,361
I'll change all the front matter

9
00:00:24,361 --> 00:00:25,708
properties accordingly.

10
00:00:26,087 --> 00:00:27,975
Let's put 6 as the day,

11
00:00:27,975 --> 00:00:30,820
and we already have a "hellblade.jpg"

12
00:00:30,820 --> 00:00:32,819
image in the right folder.

13
00:00:32,896 --> 00:00:35,232
As for the body, I'll just write

14
00:00:35,232 --> 00:00:36,838
some placeholder text.

15
00:00:36,911 --> 00:00:39,518
It's not our main focus right now.

16
00:00:39,531 --> 00:00:42,994
So, we have a "hellblade.md" file.

17
00:00:42,994 --> 00:00:45,212
This means that, if we go to our app,

18
00:00:45,212 --> 00:00:49,365
and request the "/reviews/hellblade" path,

19
00:00:49,365 --> 00:00:51,222
we'll see a page with the right

20
00:00:51,222 --> 00:00:52,540
content straight away,

21
00:00:52,600 --> 00:00:56,122
without having to modify any JavaScript code.

22
00:00:56,122 --> 00:00:59,111
The ReviewPage component will automatically

23
00:00:59,111 --> 00:01:01,961
load the data from the new Markdown file,

24
00:01:02,030 --> 00:01:04,105
based on the URL path.

25
00:01:04,105 --> 00:01:06,903
However, if we go to the Reviews page,

26
00:01:06,903 --> 00:01:09,712
we won't see Hellblade in this list.

27
00:01:09,712 --> 00:01:12,783
That's because, in the ReviewsPage component,

28
00:01:12,783 --> 00:01:15,250
we only have two list items,

29
00:01:15,343 --> 00:01:18,388
for Hollow Knight and Stardew Valley.

30
00:01:18,388 --> 00:01:20,491
Now, we don't really want to

31
00:01:20,491 --> 00:01:22,294
manually edit this file,

32
00:01:22,370 --> 00:01:24,772
every time we add a new review.

33
00:01:24,772 --> 00:01:27,876
Why don't we generate this list automatically?

34
00:01:27,876 --> 00:01:30,412
In our "reviews.js" file,

35
00:01:30,412 --> 00:01:32,067
we could add another function,

36
00:01:32,892 --> 00:01:35,654
let's call it "getReviews" (plural).

37
00:01:35,654 --> 00:01:37,952
And here we could return an array,

38
00:01:37,952 --> 00:01:39,237
with all the items.

39
00:01:39,304 --> 00:01:42,095
We'll implement this properly in a second,

40
00:01:42,095 --> 00:01:44,402
but in the ReviewsPage we'll then

41
00:01:44,402 --> 00:01:46,709
be able to call that new function

42
00:01:46,779 --> 00:01:48,670
and get all the "reviews".

43
00:01:48,670 --> 00:01:51,187
We need to use "await", because

44
00:01:51,187 --> 00:01:52,974
getReviews is "async",

45
00:01:53,055 --> 00:01:55,474
which means we also need to declare

46
00:01:55,474 --> 00:01:57,894
this component function as "async".

47
00:01:57,963 --> 00:02:01,673
That's ok, because this is a Server Component.

48
00:02:01,673 --> 00:02:04,953
What I'll do for now is simply log the "reviews",

49
00:02:05,373 --> 00:02:07,631
so we can check the data returned

50
00:02:07,631 --> 00:02:08,999
by our new function.

51
00:02:09,173 --> 00:02:11,218
Ok, if we save, we should see

52
00:02:11,218 --> 00:02:12,980
that message in the logs.

53
00:02:13,051 --> 00:02:16,577
"reviews" is currently an empty array, of course,

54
00:02:16,577 --> 00:02:19,671
because that's what we're returning at the moment.

55
00:02:19,671 --> 00:02:22,406
Now, let's think about how to implement

56
00:02:22,406 --> 00:02:24,018
this function for real.

57
00:02:24,089 --> 00:02:26,663
To find all the available reviews,

58
00:02:26,789 --> 00:02:29,655
we could simply list the Markdown files

59
00:02:29,655 --> 00:02:33,232
that are inside the "content/reviews" folder.

60
00:02:33,232 --> 00:02:35,633
We can list the files in a folder

61
00:02:35,633 --> 00:02:38,151
by using the "readdir" function

62
00:02:38,151 --> 00:02:40,586
from the "fs" built-in module.

63
00:02:40,668 --> 00:02:44,085
So, in "getReviews" we can obtain the "files"

64
00:02:44,085 --> 00:02:47,299
by calling "readdir", which is asynchronous,

65
00:02:47,299 --> 00:02:50,846
and passing the path, that is "./content/reviews".

66
00:02:50,846 --> 00:02:53,598
Just to show you exactly what it returns,

67
00:02:53,686 --> 00:02:56,685
I'll log the "files" variable to the console.

68
00:02:56,706 --> 00:02:57,827
And if we save,

69
00:02:57,827 --> 00:03:00,444
the page in the browser reloads automatically,

70
00:03:00,444 --> 00:03:02,075
running our new code,

71
00:03:02,075 --> 00:03:04,713
and you can see that "files" is an array

72
00:03:04,713 --> 00:03:07,794
containing the name of each Markdown file.

73
00:03:07,794 --> 00:03:11,477
We'll need to strip out the ".md" extension,

74
00:03:11,477 --> 00:03:13,992
because what we want is the "slugs".

75
00:03:13,992 --> 00:03:16,705
Let's transform this "files" array.

76
00:03:16,705 --> 00:03:18,429
For a start, it's better if

77
00:03:18,429 --> 00:03:19,898
we filter the elements,

78
00:03:19,961 --> 00:03:22,794
and only keep the files that end

79
00:03:22,794 --> 00:03:25,007
with the ".md" extension,

80
00:03:25,096 --> 00:03:27,205
just in case there's some other

81
00:03:27,205 --> 00:03:28,838
file in the same folder.

82
00:03:28,906 --> 00:03:32,162
Once we're sure we only have Markdown files,

83
00:03:32,162 --> 00:03:34,020
we can use the "map" method

84
00:03:34,020 --> 00:03:35,809
to transform each element,

85
00:03:35,878 --> 00:03:38,941
and we want to "slice" the file name,

86
00:03:38,941 --> 00:03:40,728
to extract a substring,

87
00:03:40,728 --> 00:03:43,169
containing the characters from zero,

88
00:03:43,169 --> 00:03:44,660
that is the beginning,

89
00:03:44,728 --> 00:03:47,715
up until the end but excluding the

90
00:03:47,715 --> 00:03:50,088
length of the ".md" suffix.

91
00:03:50,176 --> 00:03:52,275
You can pass a negative index

92
00:03:52,275 --> 00:03:54,229
to count back from the end.

93
00:03:54,302 --> 00:03:56,599
Let's log the "slugs" value now,

94
00:03:56,599 --> 00:03:58,895
to check if our code is working.

95
00:03:58,967 --> 00:04:00,745
You can see that this way

96
00:04:00,745 --> 00:04:04,523
we correctly extract the slug from each file name.

97
00:04:04,523 --> 00:04:07,000
Normally I would write unit tests

98
00:04:07,000 --> 00:04:08,651
for this sort of code,

99
00:04:08,726 --> 00:04:11,656
but for this example I'm basically testing

100
00:04:11,656 --> 00:04:13,889
it manually with log statements.

101
00:04:13,958 --> 00:04:16,286
Anyway, once we have the "slug"

102
00:04:16,286 --> 00:04:18,664
we can get a full review object

103
00:04:18,664 --> 00:04:20,740
simply by calling our existing

104
00:04:20,740 --> 00:04:22,193
"getReview" function,

105
00:04:22,262 --> 00:04:24,612
that will read each Markdown file,

106
00:04:24,612 --> 00:04:26,685
extracting all the properties.

107
00:04:26,754 --> 00:04:30,317
So, let's iterate over each "slug" in the array,

108
00:04:30,317 --> 00:04:32,222
and for each one we can get

109
00:04:32,222 --> 00:04:33,914
the full "review" object

110
00:04:33,985 --> 00:04:36,078
by calling "getReview" passing

111
00:04:36,078 --> 00:04:37,752
that "slug" as argument.

112
00:04:37,822 --> 00:04:40,342
Note that we need to use "await"

113
00:04:40,342 --> 00:04:42,626
because "getReview" is async.

114
00:04:42,705 --> 00:04:45,351
Now, let's define a "reviews" array,

115
00:04:45,351 --> 00:04:46,821
outside of the loop,

116
00:04:46,894 --> 00:04:50,096
and we can then add each review to that array,

117
00:04:50,096 --> 00:04:51,944
using the "push" method.

118
00:04:51,944 --> 00:04:55,580
And finally, we can return the "reviews" array.

119
00:04:55,580 --> 00:04:58,087
Let's see what happens now if we save.

120
00:04:58,087 --> 00:05:00,523
There's a lot of data printed here.

121
00:05:00,523 --> 00:05:02,512
The ReviewsPage is still logging

122
00:05:02,512 --> 00:05:03,817
the data it receives,

123
00:05:03,880 --> 00:05:06,548
and you can see that "reviews" is an array

124
00:05:06,548 --> 00:05:09,226
where each element is an object with

125
00:05:09,226 --> 00:05:12,693
"title", "date", "image", and "body" properties.

126
00:05:12,693 --> 00:05:15,638
What we're missing here is the "slug".

127
00:05:15,638 --> 00:05:18,531
We'll need that property in the ReviewsPage,

128
00:05:18,531 --> 00:05:22,151
otherwise we cannot link to the right URL path.

129
00:05:22,151 --> 00:05:24,645
Let's simply add the "slug" to the

130
00:05:24,645 --> 00:05:26,918
object returned by "getReview".

131
00:05:26,992 --> 00:05:29,092
And with this, each review should

132
00:05:29,092 --> 00:05:31,129
have all the properties we need.

133
00:05:31,193 --> 00:05:32,448
You could argue that,

134
00:05:32,448 --> 00:05:34,228
in the ReviewsPage we don't

135
00:05:34,228 --> 00:05:35,744
really need the "body",

136
00:05:35,810 --> 00:05:37,855
so, as an optimization, we

137
00:05:37,855 --> 00:05:39,822
could exclude that field.

138
00:05:39,900 --> 00:05:42,089
But we would still need to read

139
00:05:42,089 --> 00:05:43,925
each Markdown file anyway,

140
00:05:43,996 --> 00:05:47,410
to extract the properties from the front matter,

141
00:05:47,410 --> 00:05:50,468
so we might as well leave this code as it is.

142
00:05:50,468 --> 00:05:53,098
And this is how we can automatically

143
00:05:53,098 --> 00:05:54,559
get all the reviews.

144
00:05:54,632 --> 00:05:58,611
The next step is to display that data in our page,

145
00:05:58,611 --> 00:06:00,721
but we'll do that in the next video.

