‫Now, it's time to load our cities data
‫from a fake API again
‫and then to actually render that data into the UI.
‫And so let's start by actually creating
‫the CityList component.
‫So CityList.jsx,
‫and then we use our snippet,
‫and let's also immediately bring in our CSS module.
‫So our CSM snippet.
‫And so now, let's use that style object
‫here in an unordered list.
‫So styles.cityList.
‫And here, for now, let's just write something.
‫And so now, here we want to finally replace
‫this simple paragraph with the list of cities.
‫So in this one and in the next child route actually as well.
‫So CityList,
‫let's close that here, and the same thing here again.
‫Give it a save, and then we get a problem.
‫So, what do we have here?
‫So apparently, it has something to do with the style.
‫And here, of course, it needs to be className.
‫And yeah, that looks a lot better.
‫Okay, so next up, let's actually set up our fake API again
‫so that we can then fetch our city data from there.
‫And so just like in the previous section,
‫for that, we will install the json-server package.
‫So please, go ahead and do that right now.
‫And again, inside our current project folder.
‫And then we will just come here
‫to our package.json file
‫and add right here a new script
‫so that we can then run and start that json-server
‫right from our console.
‫So let's call this one server,
‫and the command will be
‫json-server --watch,
‫and then it's at data/cities.json.
‫Then let's specify also the port at 8000.
‫And this time around, I also want to add an artificial delay
‫so that it looks as if the API always takes half a second
‫to actually fetch the data.
‫So let's reload here, just to get rid of that error,
‫and now, here we should be able to run this.
‫So, npm run server.
‫And here, again, we have a problem
‫where this is already in use, so let's try 9000.
‫And there we go.
‫So now that works.
‫So if we copy now this localhost and then 9000,
‫you see that, well, we don't really have our data,
‫but that's because here I need to add /cities.
‫And so here are three cities
‫that we can now load into our application
‫using the fetch function, just like before.
‫So, where are we going to do that?
‫Well, we could do it right here in the CityList
‫because this is where we will first need this data,
‫but we will later on also need this data
‫in some other places.
‫And in particular, if we look at our demo here,
‫we need it here also in these countries,
‫so these countries will be derived from all the cities,
‫and finally, we also need it to display these markers here.
‫So each city gets its own marker with some data of the city,
‫and so then, there we will need that data again.
‫And so let's just place that data, for now at least,
‫here in the App component.
‫So basically, as global state that will be available
‫to all components that we want to pass in using props.
‫So,
‫let's create a new piece of state called cities,
‫and then setCities,
‫and then our useState hook
‫starting with just an empty object,
‫and then let's also get a quick isLoading state
‫and setIsLoading.
‫All right, and then we want to load this data here
‫right on mount.
‫So let's use useEffect.
‫So on mount, so on the initial render of this component.
‫Now, it doesn't make a lot of sense actually
‫to load this data right as the entire application loads,
‫for example, right here.
‫So as it is right now,
‫we actually start loading this city data
‫even as we are only on this page here,
‫so on one of these pages,
‫where we don't really need that data yet,
‫but, for now, let's just do it this way
‫because, in the next section,
‫we will even change this anyway.
‫So let's define an async function here
‫called fetchCities.
‫And then, here we are missing,
‫of course, that function keyword.
‫And so let's, as always, create a variable called res
‫and then await a fetch request to our API.
‫So let's just grab that there.
‫And actually, let's place that URL outside.
‫So at least this part here, but not the cities part.
‫So this is basically our BASE_URL,
‫and now, here we can construct our URL for the fetch
‫based on this BASE_URL.
‫And so this then is a bit more reusable.
‫So in case we need to change this BASE_URL later,
‫then we don't need to search in our code
‫for this fetch request.
‫So then we need to await res.json,
‫and then set the cities with the data that we get back.
‫Then, in case there is some error,
‫let's add a catch block and just alert something
‫was an error loading data.
‫And what's wrong here?
‫Ah, yeah, of course,
‫I forgot to add that catch block,
‫or that try block, actually.
‫Then here we need to close this function,
‫and then we need our finally
‫to set our loading state back to false.
‫So setIsLoading to false,
‫and of course, in the very beginning,
‫we need to set it to true.
‫So this is pretty standard stuff
‫that we have been doing all the time here.
‫Okay.
‫And so, right now, this should already been working
‫at the very beginning,
‫so when we first load our application.
‫Let's try that again.
‫And if we check out our Network tab,
‫well, then we cannot really see that,
‫but it should be there.
‫So it's easier probably to check our component.
‫And,
‫yeah, so here is our city data.
‫And so now, we want to pass that data
‫so that here we can show a loading spinner
‫or we can show then the data itself.
‫So let's do that.
‫And so now, we see the advantage
‫of why here we need to use an element and not a component
‫because now we can very easily pass in that data.
‫So cities will be cities,
‫and then isLoading equals isLoading,
‫and the same thing here.
‫And don't worry about this duplicate code here
‫because we will actually get rid of these props
‫when we start talking about context in the next section.
‫But anyway, now let's use this data right here.
‫And first of all, we need to accept that.
‫So cities and isLoading.
‫And so now, the first thing that we want to do is to,
‫if isLoading, then we want to just return a spinner here,
‫so something indicating that the page is loading.
‫And only if that's not the case,
‫we want to then return this actual list.
‫So we already have a spinner component, actually.
‫I think that's what it's called.
‫Yeah, so right here, we have the spinner.
‫And if you want, you can, of course,
‫check out all the code for that.
‫But anyway, let's now just import that really quick here.
‫So from and then Spinner.
‫Okay, but, otherwise,
‫we want to, of course, render this list.
‫And so, as always, what we do is to take our cities
‫and then map over them.
‫So for each city object,
‫we want to create one city component.
‫And so let's actually create that component here first.
‫So,
‫let's then call that the CityItem.jsx.
‫Okay.
‫And so this will then take in the city.
‫And here it will return one li.
‫And let's just type city for now.
‫And then here we can bring that city item in
‫and pass as a prop the current city.
‫So pretty standard stuff.
‫And let's also define the key as the city.id.
‫All right.
‫And so here we have one city text for each of the cities.
‫So let's reload this,
‫and we have a problem.
‫So cities.map is not a function.
‫Ah, and I know why that is.
‫It's because, by default, here we have this empty object
‫which should actually be an empty array.
‫So let's see.
‫And very shortly, you saw the loading spinner there
‫which should have lasted a bit longer.
‫So maybe we have some problem here with the delay.
‫And here it should actually be two dashes, like this.
‫So then we need to quit the process with Control+C
‫and run it again.
‫All right, try that again.
‫And yeah, beautiful.
‫That looked a bit better there.
‫So it seems a bit more real this way.
‫All right,
‫and now this component here is now almost finished,
‫and so let's take care of the city items themselves.
‫So first of all, each of them has some styles,
‫so let's import them here,
‫and then the class name should be
‫styles.cityItem.
‫And we already see some change there,
‫but now let's work on the content itself.
‫So here the class is style.emoji
‫because here we will display the emoji.
‫And let's actually destructure each of these cities.
‫And to do that, let's first take a look
‫at the shape of the objects.
‫So right here, so we get the city name, the country,
‫the emoji, the date, and some notes.
‫Now, we're not going to need all of them,
‫so let's just destructure the ones that we need.
‫So we want the cityName, of course,
‫the emoji, and the date for now.
‫And so that is going to come out of city.
‫And so here let's now use the emoji,
‫and then let's keep going.
‫So className
‫styles.name.
‫And then here let's use the cityName.
‫Yeah, nice.
‫This is already starting to look similar
‫to what we have here.
‫Now, we're just missing the date.
‫And then this button here, we will add it later.
‫Or maybe we will actually add it now,
‫but we can just give it no functionality.
‫So here, let's actually use the time HTML element.
‫And so then here the date.
‫And actually, let's format this date a little bit.
‫Because like this, it doesn't look really nice.
‫And I think I have a function for that
‫already here in the City component.
‫So something like this.
‫Let's just adapt this a bit.
‫So placing this outside the component, of course,
‫so that it doesn't always get recreated.
‫So here, let's just remove the weekday,
‫which we don't really care about.
‫And so then let's wrap that date
‫into a formatDate function call.
‫Nice. So almost the same.
‫Now, let's just add this button
‫and wrap that into parenthesis here.
‫Okay, and then the button itself.
‫So a bit annoying that VS Code
‫always places those quotes there.
‫Maybe there is some way of changing that default.
‫And if you know about that, then please let me know.
‫But anyway, now here we have that button,
‫which, of course, will not do anything now,
‫but we will take care of that later.
‫So this is starting to look really beautiful.
‫And now, to finish, let's just take care of the situation
‫in which there is no cities yet.
‫So imagining that the user uses the application
‫for the very first time, then there will be no data yet.
‫So let's duplicate this here,
‫just so we don't lose the data,
‫and then let's just remove everything
‫so we get just this empty array.
‫So if we reload now, then we get nothing.
‫We also don't get an error,
‫but it looks a bit, well, empty like that.
‫And so let's change that right here
‫in the CityList component.
‫So we can do some more conditional rendering.
‫We are already testing for that situation,
‫but let's also say, if there is no items,
‫so if cities.length is nonexistent,
‫then let's return some other component
‫that it also already included,
‫which is this Message component.
‫So this is, again, just a presentational component
‫which all it does is to receive a message string,
‫and then it is placed then nicely in the UI
‫with this emoji right there.
‫So let's use that.
‫And we pass in the message prop.
‫Lowercase, please.
‫Add your first city
‫by clicking on a city on the map.
‫All right.
‫Of course, now, our app doesn't know about this.
‫But there we go.
‫Beautiful.
‫Now, of course, we cannot do that yet.
‫And so let's just get all the data back here,
‫give it a save, and delete this file.
‫And so, with this, we have actually finished this lecture.