﻿1
00:00:01,110 --> 00:00:04,140
‫Now, it's time to load our cities data

2
00:00:04,140 --> 00:00:06,360
‫from a fake API again

3
00:00:06,360 --> 00:00:10,263
‫and then to actually render that data into the UI.

4
00:00:11,850 --> 00:00:14,160
‫And so let's start by actually creating

5
00:00:14,160 --> 00:00:16,053
‫the CityList component.

6
00:00:19,761 --> 00:00:21,094
‫So CityList.jsx,

7
00:00:22,890 --> 00:00:25,440
‫and then we use our snippet,

8
00:00:25,440 --> 00:00:29,703
‫and let's also immediately bring in our CSS module.

9
00:00:30,840 --> 00:00:33,270
‫So our CSM snippet.

10
00:00:33,270 --> 00:00:36,270
‫And so now, let's use that style object

11
00:00:36,270 --> 00:00:38,583
‫here in an unordered list.

12
00:00:39,750 --> 00:00:43,173
‫So styles.cityList.

13
00:00:46,080 --> 00:00:48,843
‫And here, for now, let's just write something.

14
00:00:50,010 --> 00:00:54,360
‫And so now, here we want to finally replace

15
00:00:54,360 --> 00:00:58,770
‫this simple paragraph with the list of cities.

16
00:00:58,770 --> 00:01:02,553
‫So in this one and in the next child route actually as well.

17
00:01:03,780 --> 00:01:04,653
‫So CityList,

18
00:01:06,420 --> 00:01:10,443
‫let's close that here, and the same thing here again.

19
00:01:14,280 --> 00:01:18,360
‫Give it a save, and then we get a problem.

20
00:01:18,360 --> 00:01:19,773
‫So, what do we have here?

21
00:01:23,700 --> 00:01:27,720
‫So apparently, it has something to do with the style.

22
00:01:27,720 --> 00:01:32,720
‫And here, of course, it needs to be className.

23
00:01:35,130 --> 00:01:38,403
‫And yeah, that looks a lot better.

24
00:01:40,110 --> 00:01:45,110
‫Okay, so next up, let's actually set up our fake API again

25
00:01:45,113 --> 00:01:49,590
‫so that we can then fetch our city data from there.

26
00:01:49,590 --> 00:01:51,690
‫And so just like in the previous section,

27
00:01:51,690 --> 00:01:56,200
‫for that, we will install the json-server package.

28
00:01:57,840 --> 00:02:00,720
‫So please, go ahead and do that right now.

29
00:02:00,720 --> 00:02:04,410
‫And again, inside our current project folder.

30
00:02:04,410 --> 00:02:06,600
‫And then we will just come here

31
00:02:06,600 --> 00:02:09,390
‫to our package.json file

32
00:02:09,390 --> 00:02:13,860
‫and add right here a new script

33
00:02:13,860 --> 00:02:17,730
‫so that we can then run and start that json-server

34
00:02:17,730 --> 00:02:19,950
‫right from our console.

35
00:02:19,950 --> 00:02:22,770
‫So let's call this one server,

36
00:02:22,770 --> 00:02:24,580
‫and the command will be

37
00:02:26,250 --> 00:02:30,660
‫json-server --watch,

38
00:02:30,660 --> 00:02:35,010
‫and then it's at data/cities.json.

39
00:02:38,610 --> 00:02:43,050
‫Then let's specify also the port at 8000.

40
00:02:43,050 --> 00:02:46,900
‫And this time around, I also want to add an artificial delay

41
00:02:47,820 --> 00:02:52,560
‫so that it looks as if the API always takes half a second

42
00:02:52,560 --> 00:02:54,183
‫to actually fetch the data.

43
00:02:55,260 --> 00:02:59,610
‫So let's reload here, just to get rid of that error,

44
00:02:59,610 --> 00:03:03,060
‫and now, here we should be able to run this.

45
00:03:03,060 --> 00:03:06,063
‫So, npm run server.

46
00:03:08,610 --> 00:03:10,170
‫And here, again, we have a problem

47
00:03:10,170 --> 00:03:15,003
‫where this is already in use, so let's try 9000.

48
00:03:17,757 --> 00:03:19,320
‫And there we go.

49
00:03:19,320 --> 00:03:20,643
‫So now that works.

50
00:03:22,110 --> 00:03:27,110
‫So if we copy now this localhost and then 9000,

51
00:03:28,560 --> 00:03:32,610
‫you see that, well, we don't really have our data,

52
00:03:32,610 --> 00:03:36,930
‫but that's because here I need to add /cities.

53
00:03:36,930 --> 00:03:39,060
‫And so here are three cities

54
00:03:39,060 --> 00:03:42,330
‫that we can now load into our application

55
00:03:42,330 --> 00:03:45,363
‫using the fetch function, just like before.

56
00:03:46,500 --> 00:03:49,590
‫So, where are we going to do that?

57
00:03:49,590 --> 00:03:53,280
‫Well, we could do it right here in the CityList

58
00:03:53,280 --> 00:03:56,880
‫because this is where we will first need this data,

59
00:03:56,880 --> 00:03:59,550
‫but we will later on also need this data

60
00:03:59,550 --> 00:04:01,650
‫in some other places.

61
00:04:01,650 --> 00:04:05,040
‫And in particular, if we look at our demo here,

62
00:04:05,040 --> 00:04:08,310
‫we need it here also in these countries,

63
00:04:08,310 --> 00:04:11,640
‫so these countries will be derived from all the cities,

64
00:04:11,640 --> 00:04:16,640
‫and finally, we also need it to display these markers here.

65
00:04:18,210 --> 00:04:22,770
‫So each city gets its own marker with some data of the city,

66
00:04:22,770 --> 00:04:25,860
‫and so then, there we will need that data again.

67
00:04:25,860 --> 00:04:29,940
‫And so let's just place that data, for now at least,

68
00:04:29,940 --> 00:04:32,100
‫here in the App component.

69
00:04:32,100 --> 00:04:35,280
‫So basically, as global state that will be available

70
00:04:35,280 --> 00:04:38,823
‫to all components that we want to pass in using props.

71
00:04:41,400 --> 00:04:42,233
‫So,

72
00:04:44,280 --> 00:04:49,280
‫let's create a new piece of state called cities,

73
00:04:49,380 --> 00:04:52,233
‫and then setCities,

74
00:04:53,580 --> 00:04:57,090
‫and then our useState hook

75
00:04:57,090 --> 00:04:59,910
‫starting with just an empty object,

76
00:04:59,910 --> 00:05:04,480
‫and then let's also get a quick isLoading state

77
00:05:06,060 --> 00:05:09,873
‫and setIsLoading.

78
00:05:15,210 --> 00:05:18,450
‫All right, and then we want to load this data here

79
00:05:18,450 --> 00:05:20,433
‫right on mount.

80
00:05:22,170 --> 00:05:24,057
‫So let's use useEffect.

81
00:05:28,490 --> 00:05:33,120
‫So on mount, so on the initial render of this component.

82
00:05:33,120 --> 00:05:35,850
‫Now, it doesn't make a lot of sense actually

83
00:05:35,850 --> 00:05:39,960
‫to load this data right as the entire application loads,

84
00:05:39,960 --> 00:05:43,110
‫for example, right here.

85
00:05:43,110 --> 00:05:44,730
‫So as it is right now,

86
00:05:44,730 --> 00:05:47,280
‫we actually start loading this city data

87
00:05:47,280 --> 00:05:50,490
‫even as we are only on this page here,

88
00:05:50,490 --> 00:05:52,620
‫so on one of these pages,

89
00:05:52,620 --> 00:05:55,470
‫where we don't really need that data yet,

90
00:05:55,470 --> 00:05:58,170
‫but, for now, let's just do it this way

91
00:05:58,170 --> 00:05:59,640
‫because, in the next section,

92
00:05:59,640 --> 00:06:02,403
‫we will even change this anyway.

93
00:06:03,780 --> 00:06:06,810
‫So let's define an async function here

94
00:06:06,810 --> 00:06:08,473
‫called fetchCities.

95
00:06:14,580 --> 00:06:16,230
‫And then, here we are missing,

96
00:06:16,230 --> 00:06:18,093
‫of course, that function keyword.

97
00:06:19,806 --> 00:06:24,660
‫And so let's, as always, create a variable called res

98
00:06:24,660 --> 00:06:29,077
‫and then await a fetch request to our API.

99
00:06:30,630 --> 00:06:32,283
‫So let's just grab that there.

100
00:06:34,170 --> 00:06:39,063
‫And actually, let's place that URL outside.

101
00:06:42,090 --> 00:06:45,543
‫So at least this part here, but not the cities part.

102
00:06:46,710 --> 00:06:50,670
‫So this is basically our BASE_URL,

103
00:06:50,670 --> 00:06:55,670
‫and now, here we can construct our URL for the fetch

104
00:06:56,430 --> 00:06:57,843
‫based on this BASE_URL.

105
00:06:58,860 --> 00:07:02,730
‫And so this then is a bit more reusable.

106
00:07:02,730 --> 00:07:05,880
‫So in case we need to change this BASE_URL later,

107
00:07:05,880 --> 00:07:08,130
‫then we don't need to search in our code

108
00:07:08,130 --> 00:07:09,603
‫for this fetch request.

109
00:07:11,850 --> 00:07:16,833
‫So then we need to await res.json,

110
00:07:17,730 --> 00:07:21,903
‫and then set the cities with the data that we get back.

111
00:07:22,860 --> 00:07:26,250
‫Then, in case there is some error,

112
00:07:26,250 --> 00:07:29,950
‫let's add a catch block and just alert something

113
00:07:31,770 --> 00:07:36,303
‫was an error loading data.

114
00:07:37,830 --> 00:07:40,503
‫And what's wrong here?

115
00:07:41,910 --> 00:07:43,590
‫Ah, yeah, of course,

116
00:07:43,590 --> 00:07:47,553
‫I forgot to add that catch block,

117
00:07:49,288 --> 00:07:51,693
‫or that try block, actually.

118
00:07:52,830 --> 00:07:55,890
‫Then here we need to close this function,

119
00:07:55,890 --> 00:07:59,130
‫and then we need our finally

120
00:07:59,130 --> 00:08:04,050
‫to set our loading state back to false.

121
00:08:04,050 --> 00:08:07,920
‫So setIsLoading to false,

122
00:08:07,920 --> 00:08:09,630
‫and of course, in the very beginning,

123
00:08:09,630 --> 00:08:14,280
‫we need to set it to true.

124
00:08:14,280 --> 00:08:16,080
‫So this is pretty standard stuff

125
00:08:16,080 --> 00:08:18,723
‫that we have been doing all the time here.

126
00:08:23,940 --> 00:08:24,900
‫Okay.

127
00:08:24,900 --> 00:08:28,080
‫And so, right now, this should already been working

128
00:08:28,080 --> 00:08:29,460
‫at the very beginning,

129
00:08:29,460 --> 00:08:32,193
‫so when we first load our application.

130
00:08:33,120 --> 00:08:35,010
‫Let's try that again.

131
00:08:35,010 --> 00:08:37,233
‫And if we check out our Network tab,

132
00:08:38,700 --> 00:08:40,890
‫well, then we cannot really see that,

133
00:08:40,890 --> 00:08:42,690
‫but it should be there.

134
00:08:42,690 --> 00:08:46,080
‫So it's easier probably to check our component.

135
00:08:46,080 --> 00:08:46,913
‫And,

136
00:08:49,590 --> 00:08:53,073
‫yeah, so here is our city data.

137
00:08:55,950 --> 00:08:58,860
‫And so now, we want to pass that data

138
00:08:58,860 --> 00:09:01,740
‫so that here we can show a loading spinner

139
00:09:01,740 --> 00:09:05,103
‫or we can show then the data itself.

140
00:09:07,110 --> 00:09:08,970
‫So let's do that.

141
00:09:08,970 --> 00:09:10,920
‫And so now, we see the advantage

142
00:09:10,920 --> 00:09:15,060
‫of why here we need to use an element and not a component

143
00:09:15,060 --> 00:09:18,273
‫because now we can very easily pass in that data.

144
00:09:19,440 --> 00:09:22,890
‫So cities will be cities,

145
00:09:22,890 --> 00:09:27,390
‫and then isLoading equals isLoading,

146
00:09:27,390 --> 00:09:28,833
‫and the same thing here.

147
00:09:32,040 --> 00:09:34,710
‫And don't worry about this duplicate code here

148
00:09:34,710 --> 00:09:38,280
‫because we will actually get rid of these props

149
00:09:38,280 --> 00:09:42,003
‫when we start talking about context in the next section.

150
00:09:43,320 --> 00:09:47,460
‫But anyway, now let's use this data right here.

151
00:09:47,460 --> 00:09:51,450
‫And first of all, we need to accept that.

152
00:09:51,450 --> 00:09:53,817
‫So cities and isLoading.

153
00:09:55,170 --> 00:09:58,590
‫And so now, the first thing that we want to do is to,

154
00:09:58,590 --> 00:10:03,590
‫if isLoading, then we want to just return a spinner here,

155
00:10:04,410 --> 00:10:07,590
‫so something indicating that the page is loading.

156
00:10:07,590 --> 00:10:09,510
‫And only if that's not the case,

157
00:10:09,510 --> 00:10:13,383
‫we want to then return this actual list.

158
00:10:14,790 --> 00:10:19,790
‫So we already have a spinner component, actually.

159
00:10:20,070 --> 00:10:21,670
‫I think that's what it's called.

160
00:10:22,620 --> 00:10:25,653
‫Yeah, so right here, we have the spinner.

161
00:10:26,610 --> 00:10:28,230
‫And if you want, you can, of course,

162
00:10:28,230 --> 00:10:31,413
‫check out all the code for that.

163
00:10:33,720 --> 00:10:37,383
‫But anyway, let's now just import that really quick here.

164
00:10:39,300 --> 00:10:44,300
‫So from and then Spinner.

165
00:10:44,820 --> 00:10:46,230
‫Okay, but, otherwise,

166
00:10:46,230 --> 00:10:49,590
‫we want to, of course, render this list.

167
00:10:49,590 --> 00:10:53,940
‫And so, as always, what we do is to take our cities

168
00:10:53,940 --> 00:10:56,280
‫and then map over them.

169
00:10:56,280 --> 00:10:58,200
‫So for each city object,

170
00:10:58,200 --> 00:11:01,470
‫we want to create one city component.

171
00:11:01,470 --> 00:11:05,193
‫And so let's actually create that component here first.

172
00:11:06,660 --> 00:11:07,503
‫So,

173
00:11:09,000 --> 00:11:13,923
‫let's then call that the CityItem.jsx.

174
00:11:15,461 --> 00:11:16,383
‫Okay.

175
00:11:18,090 --> 00:11:20,943
‫And so this will then take in the city.

176
00:11:24,360 --> 00:11:26,823
‫And here it will return one li.

177
00:11:28,860 --> 00:11:32,010
‫And let's just type city for now.

178
00:11:32,010 --> 00:11:35,940
‫And then here we can bring that city item in

179
00:11:35,940 --> 00:11:38,703
‫and pass as a prop the current city.

180
00:11:39,720 --> 00:11:42,270
‫So pretty standard stuff.

181
00:11:42,270 --> 00:11:47,270
‫And let's also define the key as the city.id.

182
00:11:48,930 --> 00:11:50,160
‫All right.

183
00:11:50,160 --> 00:11:55,020
‫And so here we have one city text for each of the cities.

184
00:11:55,020 --> 00:11:56,313
‫So let's reload this,

185
00:11:57,990 --> 00:12:00,093
‫and we have a problem.

186
00:12:02,790 --> 00:12:06,060
‫So cities.map is not a function.

187
00:12:06,060 --> 00:12:08,040
‫Ah, and I know why that is.

188
00:12:08,040 --> 00:12:12,490
‫It's because, by default, here we have this empty object

189
00:12:14,160 --> 00:12:16,803
‫which should actually be an empty array.

190
00:12:18,780 --> 00:12:20,040
‫So let's see.

191
00:12:20,040 --> 00:12:23,370
‫And very shortly, you saw the loading spinner there

192
00:12:23,370 --> 00:12:25,530
‫which should have lasted a bit longer.

193
00:12:25,530 --> 00:12:28,683
‫So maybe we have some problem here with the delay.

194
00:12:30,870 --> 00:12:34,953
‫And here it should actually be two dashes, like this.

195
00:12:35,970 --> 00:12:40,680
‫So then we need to quit the process with Control+C

196
00:12:40,680 --> 00:12:41,913
‫and run it again.

197
00:12:45,090 --> 00:12:47,220
‫All right, try that again.

198
00:12:47,220 --> 00:12:49,320
‫And yeah, beautiful.

199
00:12:49,320 --> 00:12:51,180
‫That looked a bit better there.

200
00:12:51,180 --> 00:12:53,613
‫So it seems a bit more real this way.

201
00:12:55,170 --> 00:12:57,000
‫All right,

202
00:12:57,000 --> 00:13:01,680
‫and now this component here is now almost finished,

203
00:13:01,680 --> 00:13:06,420
‫and so let's take care of the city items themselves.

204
00:13:06,420 --> 00:13:09,483
‫So first of all, each of them has some styles,

205
00:13:10,530 --> 00:13:12,660
‫so let's import them here,

206
00:13:12,660 --> 00:13:16,000
‫and then the class name should be

207
00:13:18,030 --> 00:13:19,743
‫styles.cityItem.

208
00:13:24,210 --> 00:13:26,253
‫And we already see some change there,

209
00:13:27,180 --> 00:13:31,140
‫but now let's work on the content itself.

210
00:13:31,140 --> 00:13:35,370
‫So here the class is style.emoji

211
00:13:35,370 --> 00:13:39,510
‫because here we will display the emoji.

212
00:13:39,510 --> 00:13:43,380
‫And let's actually destructure each of these cities.

213
00:13:43,380 --> 00:13:45,720
‫And to do that, let's first take a look

214
00:13:45,720 --> 00:13:48,033
‫at the shape of the objects.

215
00:13:49,710 --> 00:13:53,700
‫So right here, so we get the city name, the country,

216
00:13:53,700 --> 00:13:57,000
‫the emoji, the date, and some notes.

217
00:13:57,000 --> 00:13:59,550
‫Now, we're not going to need all of them,

218
00:13:59,550 --> 00:14:02,103
‫so let's just destructure the ones that we need.

219
00:14:02,940 --> 00:14:06,930
‫So we want the cityName, of course,

220
00:14:06,930 --> 00:14:11,930
‫the emoji, and the date for now.

221
00:14:12,330 --> 00:14:15,510
‫And so that is going to come out of city.

222
00:14:15,510 --> 00:14:17,967
‫And so here let's now use the emoji,

223
00:14:21,207 --> 00:14:23,700
‫and then let's keep going.

224
00:14:23,700 --> 00:14:24,813
‫So className

225
00:14:26,910 --> 00:14:29,523
‫styles.name.

226
00:14:33,270 --> 00:14:35,433
‫And then here let's use the cityName.

227
00:14:39,780 --> 00:14:41,040
‫Yeah, nice.

228
00:14:41,040 --> 00:14:43,830
‫This is already starting to look similar

229
00:14:43,830 --> 00:14:45,900
‫to what we have here.

230
00:14:45,900 --> 00:14:47,640
‫Now, we're just missing the date.

231
00:14:47,640 --> 00:14:50,193
‫And then this button here, we will add it later.

232
00:14:53,070 --> 00:14:55,383
‫Or maybe we will actually add it now,

233
00:14:56,400 --> 00:15:01,400
‫but we can just give it no functionality.

234
00:15:03,120 --> 00:15:08,073
‫So here, let's actually use the time HTML element.

235
00:15:09,540 --> 00:15:11,730
‫And so then here the date.

236
00:15:11,730 --> 00:15:14,490
‫And actually, let's format this date a little bit.

237
00:15:14,490 --> 00:15:17,430
‫Because like this, it doesn't look really nice.

238
00:15:17,430 --> 00:15:20,970
‫And I think I have a function for that

239
00:15:20,970 --> 00:15:23,523
‫already here in the City component.

240
00:15:24,480 --> 00:15:26,343
‫So something like this.

241
00:15:27,240 --> 00:15:29,463
‫Let's just adapt this a bit.

242
00:15:30,330 --> 00:15:33,390
‫So placing this outside the component, of course,

243
00:15:33,390 --> 00:15:35,763
‫so that it doesn't always get recreated.

244
00:15:36,870 --> 00:15:39,390
‫So here, let's just remove the weekday,

245
00:15:39,390 --> 00:15:41,610
‫which we don't really care about.

246
00:15:41,610 --> 00:15:44,340
‫And so then let's wrap that date

247
00:15:44,340 --> 00:15:47,373
‫into a formatDate function call.

248
00:15:49,080 --> 00:15:51,510
‫Nice. So almost the same.

249
00:15:51,510 --> 00:15:53,220
‫Now, let's just add this button

250
00:15:53,220 --> 00:15:55,683
‫and wrap that into parenthesis here.

251
00:15:58,920 --> 00:16:02,313
‫Okay, and then the button itself.

252
00:16:03,540 --> 00:16:05,400
‫So a bit annoying that VS Code

253
00:16:05,400 --> 00:16:09,093
‫always places those quotes there.

254
00:16:10,410 --> 00:16:13,350
‫Maybe there is some way of changing that default.

255
00:16:13,350 --> 00:16:15,950
‫And if you know about that, then please let me know.

256
00:16:18,300 --> 00:16:21,510
‫But anyway, now here we have that button,

257
00:16:21,510 --> 00:16:24,120
‫which, of course, will not do anything now,

258
00:16:24,120 --> 00:16:27,360
‫but we will take care of that later.

259
00:16:27,360 --> 00:16:30,330
‫So this is starting to look really beautiful.

260
00:16:30,330 --> 00:16:34,110
‫And now, to finish, let's just take care of the situation

261
00:16:34,110 --> 00:16:36,870
‫in which there is no cities yet.

262
00:16:36,870 --> 00:16:39,870
‫So imagining that the user uses the application

263
00:16:39,870 --> 00:16:44,580
‫for the very first time, then there will be no data yet.

264
00:16:44,580 --> 00:16:47,580
‫So let's duplicate this here,

265
00:16:47,580 --> 00:16:49,440
‫just so we don't lose the data,

266
00:16:49,440 --> 00:16:54,150
‫and then let's just remove everything

267
00:16:54,150 --> 00:16:57,153
‫so we get just this empty array.

268
00:16:58,020 --> 00:17:01,050
‫So if we reload now, then we get nothing.

269
00:17:01,050 --> 00:17:02,760
‫We also don't get an error,

270
00:17:02,760 --> 00:17:06,960
‫but it looks a bit, well, empty like that.

271
00:17:06,960 --> 00:17:09,917
‫And so let's change that right here

272
00:17:09,917 --> 00:17:12,663
‫in the CityList component.

273
00:17:13,860 --> 00:17:16,593
‫So we can do some more conditional rendering.

274
00:17:17,700 --> 00:17:20,400
‫We are already testing for that situation,

275
00:17:20,400 --> 00:17:24,870
‫but let's also say, if there is no items,

276
00:17:24,870 --> 00:17:29,870
‫so if cities.length is nonexistent,

277
00:17:30,840 --> 00:17:33,630
‫then let's return some other component

278
00:17:33,630 --> 00:17:35,940
‫that it also already included,

279
00:17:35,940 --> 00:17:38,430
‫which is this Message component.

280
00:17:38,430 --> 00:17:41,520
‫So this is, again, just a presentational component

281
00:17:41,520 --> 00:17:45,330
‫which all it does is to receive a message string,

282
00:17:45,330 --> 00:17:48,210
‫and then it is placed then nicely in the UI

283
00:17:48,210 --> 00:17:50,293
‫with this emoji right there.

284
00:17:51,840 --> 00:17:54,333
‫So let's use that.

285
00:17:56,550 --> 00:17:59,100
‫And we pass in the message prop.

286
00:17:59,100 --> 00:18:00,483
‫Lowercase, please.

287
00:18:03,180 --> 00:18:05,820
‫Add your first city

288
00:18:05,820 --> 00:18:10,053
‫by clicking on a city on the map.

289
00:18:11,130 --> 00:18:12,063
‫All right.

290
00:18:13,260 --> 00:18:16,743
‫Of course, now, our app doesn't know about this.

291
00:18:18,300 --> 00:18:21,240
‫But there we go.

292
00:18:21,240 --> 00:18:22,320
‫Beautiful.

293
00:18:22,320 --> 00:18:24,420
‫Now, of course, we cannot do that yet.

294
00:18:24,420 --> 00:18:27,843
‫And so let's just get all the data back here,

295
00:18:29,340 --> 00:18:33,873
‫give it a save, and delete this file.

296
00:18:35,400 --> 00:18:39,123
‫And so, with this, we have actually finished this lecture.

