‫So in this lecture,
‫we're gonna use the position data
‫in order to fetch all necessary information
‫about the city where the user has clicked.
‫So for example, if the user clicks here on Rome,
‫then we want to automatically fetch that data here
‫from an API, so from a reverse geocoding API.
‫And so let's now go do that.
‫So let's open up our form,
‫and now the first thing that we need to do is
‫to actually get the location data
‫from the URL into this component.
‫So reading here,
‫this global state that is stored in the url.
‫Now we already did the same thing before
‫which is right here in the map, right?
‫So the map also depends on that data
‫in order to move to the city that the user has clicked.
‫So that's this logic right here, plus this.
‫Now should we just go copy paste this
‫into this other component?
‫Well, I think that it actually makes sense
‫to create a new custom hook now.
‫So let's call this useURLPosition.js.
‫All right, and so then let's move that here
‫and grab all this.
‫And so now we are extracting some more stateful logic
‫into a custom hook.
‫Now in this case,
‫well let's first create a function here.
‫useUrlPosition.
‫So as I was saying, here,
‫we are actually creating a custom hook
‫on top of another custom hook.
‫So this is also a custom hook that is coming
‫from React Router, but this is perfectly fine.
‫So as long as our logic has at least one React hook,
‫we need to create our own custom hook
‫if we want to reuse that logic.
‫So now we need to include, start to import, that here.
‫And then what we want is to return.
‫And here, let's just actually give them more generic names,
‫because this is meant to be reusable.
‫And so yeah, let's export this.
‫And with this, we are done.
‫And so then whenever we need to position from the url,
‫we very simply just call this one function, and that's it.
‫So here, let's then import that data.
‫And here we can now again call it mapLat, and mapLng,
‫from useUrlLocation.
‫So somehow there's no auto import,
‫so let's do that ourselves.
‫So useUrlLocation like this,
‫and that actually doesn't work.
‫And I guess that's because it is actually called position.
‫So useUrlPosition.
‫So let's fix that URLPosition.
‫And so with that,
‫the map is back to working just like before.
‫And so then we can just grab this line of code,
‫and use it inside our form.
‫So placing that right here.
‫Let's try to import this now.
‫And there we go.
‫So now inside the form, we should have also the location.
‫So this is somehow not working.
‫So let's see.
‫Here it is.
‫Well, that's actually apparently not working,
‫so there's nothing in here.
‫So let's see if actually the app still works here,
‫and yeah, it does.
‫Well, let's try to lock this to the console here.
‫Maybe I just somehow didn't see it.
‫Yeah, there we go.
‫So that's working indeed.
‫And so let's now use this data
‫to actually do the reverse geocoding.
‫So getting the city information, or really any information,
‫about the GPS position that we are currently located at.
‫Let's just call this lat, and lng.
‫And then we want to fetch this data
‫right when the component mounts.
‫So that's a useEffect for that.
‫Now, the data that we're gonna fetch here is not going
‫to go into our global state,
‫so into the global city's context,
‫because this data is only relevant
‫for then creating a city's object that will be added
‫to the array.
‫So you only really need this data right here
‫in this component.
‫And so then we just fetched it right here.
‫Alright so let's, as always, create an async function,
‫and then fetchCityData for example.
‫And then a try catch block as always.
‫So we're going to need a few pieces of state here apart
‫from the ones that we already have.
‫So first, let's say, is loading,
‫then let's say geocoding,
‫and then setIsLoadingGeocoding.
‫And again, I'm using a different name here
‫because we already used IsLoading in our context,
‫so somewhere else.
‫So here we then start by setting this to true,
‫then we will have our catch block as always.
‫And then also the finally block, where in the end,
‫we setIsLoading back to false.
‫Okay?
‫So that's one of the states.
‫And then let's also create one to store the city name.
‫cityName, setCityName, or actually we already have those.
‫So city name and country are already up there.
‫So let's just move this one over there.
‫And so then let's keep writing our code here.
‫So as always, let's create a variable called response,
‫which will await fetching the actual data.
‫And here at the top of this file,
‫you should already have the url.
‫So let's grab that and I will paste down here.
‫And then out here, I will create, again,
‫a variable called BASE_URL.
‫And so this is basically all of this,
‫but then without the more specific part.
‫Okay, and so then let's here build the actual url.
‫So we want the BASE_URL, and then as we see here,
‫we add the latitude and the longitude like this.
‫Okay?
‫And so then here is where we use that data.
‫So the latitude that we got from our URL,
‫and the longitude, okay?
‫And immediately React is telling us that we now need
‫to add them as a dependency, which makes total sense.
‫Or actually let me not add it for now,
‫so that I can show you later what's gonna happen
‫if we don't do that.
‫So that's gonna be a nice exercise, I think.
‫So then we await res.json from there.
‫And then as always,
‫let's just log that to the console first.
‫Then we need to call the function out here.
‫Let's reload that.
‫And here we immediately get something.
‫So I'm not really sure where I clicked,
‫but apparently we clicked on some city
‫called Val de Mecca or something like that.
‫So this is basically what we want here.
‫So the locality, or there should actually also be a city.
‫So that's not really appearing right now.
‫So let me now demonstrate what happens
‫if I click somewhere else.
‫So now with this still open,
‫if I click here for example on Rome,
‫then you see that nothing happened,
‫even though the URL there has changed.
‫So basically the latitude and longitude have changed right?
‫However, we didn't fetch any new data.
‫And so do you know why that is?
‫Well, it's because we are missing these values here
‫in the dependency array.
‫So this function here has no way
‫of knowing that this data has actually changed,
‫and so therefore the effect is then not executed again.
‫But if we pass both of them in,
‫then our effect will know that there has been a change.
‫So now here we get the city property
‫which is what we want to use usually.
‫Now if we're just clicking on some small place,
‫like in the middle of nowhere,
‫then the city's gonna be empty,
‫and so then we can just use the locality.
‫So let's then set the city name to data.city,
‫and if that doesn't exist, then we do data.locality.
‫And then let's just account
‫for the case where that also doesn't exist.
‫And so then let's just set it to an empty string.
‫Then here we also get the country name,
‫and so let's also set the country name,
‫because later on we will want
‫to set that country also to the new city object.
‫So that's data.countryName.
‫And if we take a look here,
‫then you'll see that actually it already changed here.
‫So that's because down here in our JSX,
‫we are already referencing the city name right here.
‫And so that is already working.
‫So let's click somewhere else.
‫Like here it says Latina, so let's see.
‫And indeed it then changes everywhere here to Latina.
‫Then what we also want to do is
‫to convert that country name to an emoji,
‫so that we can then use that right here.
‫So how do we do that?
‫So should we create another piece of state here for that?
‫Well, that's actually not really necessary.
‫So we can just derive that using this function
‫that it already provided here.
‫So we can just calculate emoji here based
‫on that information.
‫So convertToEmoji, and then this simply receives
‫a country code.
‫Well, we actually don't have that country code anywhere.
‫So that's this one right here.
‫So we don't have that.
‫So if we want to get that out here,
‫we would have to create another piece of state.
‫And so instead, let's actually break what I just said,
‫and create a state variable for the emoji after all,
‫setEmoji, and then useState.
‫So you have so many pieces of state here
‫that it might even make sense to use a useReducer
‫at this point, but here let's just keep it simple,
‫and then setEmoji right here.
‫So this is not a big problem of having all
‫of these different states because these data updates,
‫as we learned before,
‫are going to be batched at least since React version 18.
‫So then here we can call that function convertToEmoji,
‫and then it's data.countryCode.
‫So let's see, then we need to remove that here.
‫And beautiful, there it is.
‫Nice.
‫So we are almost done here,
‫but now let's account for a different situation.
‫So let's say I click somewhere here,
‫in the middle of nowhere.
‫So in the water where nothing really is.
‫So then we see that the city name is this weird thing.
‫Or if I click here, then well,
‫it's something that's not really meaningful.
‫So let's see what we have.
‫So this is not a city, it's not a country,
‫so it's really nothing.
‫All the tasks has this weird locality set to that.
‫Now if I click in here,
‫that is apparently still part of the country.
‫So then here, everything works.
‫But then out here in the middle of the sea,
‫we don't have any data.
‫So we don't have any country, for example.
‫And so let's now then not display the form
‫in that situation,
‫and instead tell the user to click somewhere else.
‫So how can we do that?
‫Well, I think a good idea to do this is to create an error.
‫So right here, before even setting any state,
‫we can say that if there is no data.countryCode for example,
‫then throw a new error saying,
‫"That doesn't seem to be a city.
‫Click somewhere else."
‫More like this.
‫And then let's just add a friendly emoji here.
‫And here we need the double quotes.
‫Now okay, and then here we can catch that error,
‫and place it into our state so that then we can,
‫depending on that state, display a message right there.
‫So let's create another piece of state here
‫called geocodingError and setGeocoding Error.
‫So by default, this will be empty,
‫and we want to make it empty also here at the beginning.
‫So to basically reset the error.
‫But then if there actually is an error,
‫like this one here or even like some other error,
‫then we want to setGeocodingError to the error.message.
‫So whatever we pass here into the error
‫will become error.message.
‫And now here we can then say that
‫if there is a geocodingError,
‫then just return the message component
‫that we already created earlier.
‫So here, this then requires the message prompt
‫which is exactly going to the geocodingError.
‫And so that's already working.
‫So if I click here on this city, then it works.
‫But if I click here, then there doesn't seem to be a city.
‫Nice.
‫And now just one final thing,
‫which is also the case where the city is currently loading.
‫So isLoadingGeocoding, then return a spinner now, right?
‫So notice that that's actually a lot better.
‫So showing the user that something is happening.
‫Okay, and so with this, we are now almost ready
‫to actually add a new city like this to our city's array,
‫so into our city state and uploading it
‫to that fake API so that then,
‫it ends up here into our list.
‫And so let's move on to the next lecture and do that.