How to create and customize cluster markers in React

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey it's Lee holiday and today we're going to see how to use Advanced markers and combine that with marker clustering to take about 500 trees render them onto the map using emojis and then cluster them together into little groups so that if we zoom out we're not being bombarded with 500 trees but we're seeing sort of where the pockets of trees are and how many are in each zone so to get started this is the file we're working with and there are number of imports at the top I'm going to explain them as we need them rather than sort of going over them all at the beginning but to get started you should remember that you're going to need to npm install at v.g react gooogle maps and at goog Maps markercluster those are sort of apart from react and I'm working within nextjs those are the two sort of additional packages you're going to need to follow along with the demo today today now 500 trees that's a lot of trees where am I getting all of this data from I've got this file here trees. typescript but really I it came from the city of Toronto they provide um all of the tree locations of Toronto there's a lot more than 500 so I cut it down a little bit but we've got this huge list of trees here and it's basically like we've got a pine at this location we have a maple at this location so we're going to be taking this and rendering them all onto the map using Advanced markers to have them show up as little tree Emojis all right so let's just start first we want to get a map rendering out onto the screen so we're going to take this div and inside of here use the API provider which is a component coming from uh the vigl react Google Maps package and you can see it complaining because it's missing the API key so this is our Google Maps API key and I've put it into an environment variable and I can access it with process. env. nextt public Google Maps API key so remember uh you shouldn't Commit This to your repository but it is going to be publicly available so inside of the the Google console make sure to restrict your API key to the website that you're working in so that people can't use it on their website so inside of the API provider sort of once it's loaded the packages using our API key we want to be able to render the map so we'll put here map and close the map and it doesn't work by default we need to give it a a few things to to render out a default map the first thing is sort of where should it Center itself at the beginning so we'll give it a latitude and we'll just place it in Toronto somewhere so 43.645074 so just like that we've got nothing yet but we're going to be seeing a map very shortly so the next prop we need to pass is the zoom level these are the two sort of required um props in order for this to work correctly we're going to zoom in to 10 and you still don't see it so as a reminder um whatever container you put the map in um you need to provide a height and a width to that container otherwise the map won't have any sort of size so this div here we're going to come and just say style we're going to give it a height of 100 VH so the whole screen and we'll give it a width two of 100% so once we do that we should be able to come back we'll just refresh the page and we've got our beautiful map of Toronto being rendered and remember that we are working with uh Advanced markers in this video and for advanced markers you're going to need to give your map a map ID so this is something you can grab from the the Google Maps um console admin on the web and you can set up a map ID and then you can theme that map ID so that you can have it show up in dark mode and things like that so I've also got this in an environment variable so we'll access our next public map ID just like that and now when I come back because I'm using a map ID that was styled I get my uh dark mode map all right so we got the map on the screen why don't we work on taking these trees um and just rendering all of them out as advanced markers on the screen and we'll do that in a separate component to just uh compartmentalize what we're working with a little bit so we've got markers like that it's failing because it doesn't exist so we'll say uh function marker we'll say const markers is equal to um just this and we'll just return null for now but we'll start to fill this in I just like to sort of make make the script happy as we go and make sure that it's still rendering without any errors so the first thing we're going to do is why don't we even though we could just access our trees directly why don't we pass them down as props so we'll say trees are being passed down here and it's complaining because I haven't set up this component to re reive the trees so we're going to come down here and we're going to sort of give our prop a name and rather than saying trees why don't we say that we're working with points so we're going to receive points and because we're in typescript it's sort of like um I don't know what this is and you never used what what you were being passed so we're going to set up some types here so we're going to receive many points and each point is going to be google. maps. latlng literal so it's I can see it down at the bottom there um and a couple extra things so the main thing is that we're going to be adding something called a key and we'll use that key both to sort of have have it a unique key for when you're rendering out mapping an array of something but we're also going to use this key um as as we later start to Cluster our our points so there's each point that we're passing in and if we declare our props we're going to say that uh we're going to be receiving points and that will be um an array of these points like that and now we can come down here and we can say what you're going to be receiving our props and that cleans up typescript complaining uh it's still still grade out cuz we're not using this points yet but that's what we're going to work on right now so rather than returning null why don't we render out a fragment and in that fragment we can iterate over the points with a map so we'll map the points and we'll get access to each point and then what are we going to render each point at as we're going to render it as an advanced marker so we can say advanced marker just like this so Advanced markers if if you work with sort of the standard marker or the um I don't know the the one that you see as like a red Point down uh that you're limitting into the amount you can customize and the options you can give to that advanced markers open a lot more uh possibilities and the possibility we're going to be working with is that we can actually render each one as a a little tree emoji so if we come down here we're going to put it inside of a span just like that so that each marker doesn't show up as a little red arrow but it's showing up as a tree emoji that's one of the powers of advanced markers and each marker needs to know where it's going to be positioned so we'll say position is going to be the the point and then we also have to give it a key because uh react wants that to differentiate as your um iterating over all of the different points so we'll access just like that so if we go look at the screen now we reload and we've got 500 trees and that's a lot of trees and the map can handle this well at some point if you added enough markers it would start to sort of chug a little bit and get a little bit slow but 500 it can handle okay that said it's a little bit sort of especially as you zoom up out like it just looks like Toronto's one massive forest and especially is if we go and style this span so if we say um font size we'll set it to two RM now we just have like a mass of trees and this is where clustering is going to come in and we're going to start to sort of group them using the clusterer so that it doesn't look just like just a blob of trees once you zoom in and you get down you can start to see where these individual trees are in the city but as you're zoomed out it's just a wall of trees like that all right so the next step that we're going to do is start to sort of hook up the clusterer and we're going to first need to get access to the map itself so we're going to use um use map right here this hook and this gives us access to the actual instance of the Google Map because we're going to need to pass that to the clusterer when we instantiate it um the next thing we're going to do is we're going to need some state to keep track of all of the markers so basically what I'm talking about is the actual instance of the underlying Advanced marker we're going to need to go and access each marker store it somewhere and then we can use those markers to pass them to the cluster so that it can render them out and I'll show you how to sort of get access to the reference to the underlying Advanced marker so that we can store it inside of um this will be an object that we're working with so we're going to say it's use State and we'll start it out as an empty object and because we're working with typescript we need to set up some types here so what is this object going to look like so the first thing it's an object and the next thing is that the key is going to be a string just like that so it's going to be the same as point. key we're going to use that as the key in the object and what the value is going to be is going to be a marker so what is this marker that we're storing here um I'm importing that uh as a type from Google Maps marker cluster and if you hover over it you can see that this is either sort of the stand standard marker or an advanced marker and because we're working with Advanced markers this is exactly what we need so we're going to be storing um all of the markers here and I'll show you in a second how to get them and put them in there but the next thing we we are going to do is set up um a reference to the clusterer and we're using a reference rather than State because um we're not really trying to key rendering of of of our re react component off of the cluster itself we just need to store an instance of a cluster somewhere so we're going to put it as a ref and then we'll key off of whenever the markers change um to go and update the cluster we'll see that in a second hopefully will'll make sense as we get to it so the clusterer this will be a use ref and we're working with typescript so we're going to say that this is a marker clusterer and then uh or or null because when we start out it's going to be null just like that so the first thing we need to do is basically um in an effect hook use effect so we'll just set this up um we're going to check when we first have sort of our instance of the map so if we don't have a map yet we're not ready to set up the cluster and if we do have a map then we can say if there is already if there's not a cluster already so because it's a ref we have to say cluster. current then what'll we'll do is we'll say oops clusterer is equal to a new instance of the marker clusterer just like that and one of the things we pass into the marker cluster is the map and that's why we had the map as the the only only thing in our array of dependencies for this use effect so it's going to render and the first time we see that we have a map with a value and we haven't already set up our cluster we'll set it up for the first time perfect so we're not clustering yet but we do have access to the cluster the next thing we need to do is take these 500 Advanced markers these 500 trees and start to pass them to the cluster but we're going to do that via our State and the way we're going to do that is to use the ref here but we're going to use a callback ref so what this will do is it will give us access to the underlying marker and when we receive that marker we're going to call a function called set marker ref uh this doesn't yet exist but we're going to create it in a second and we're going to pass in the underlying instance of the actual advanced marker and we're going to pass in the point. key and using those two things we're going to update our state and start keeping track of all of the underlying markers so that we can pass them to the cluster so we need to go and Define this function here so why don't we say uh const set marker ref and that is going to be equal to a function so we'll just Define the function and this function is going to receive a marker and this marker is going to be this same type but when you're using refs with a call back it can also pass null um so basically if it if it removes the reference to this thing it's going to recall your call back but this time with null so we need to keep track of that that we may receive a marker or we may receive nothing but we will always receive this key here which is going to be a string that we're passing up as the point. key okay so we need to do a little bit of work here at the beginning um and the first we would just want to save react from doing some additional work and actually you know what we're going to add that after because I've worked on this demo before and you're going to see an error that comes up and then I'll show us how to solve that error so why don't we just get right to it we've called set marker ref with with our marker and our point. key and we're going to update the mark the state so we're going to call set markers and we're going to do it with a a call back that gives us access to our previous state value just like that so what we can do here is we can say if there's a marker because remember it might be null we're going to return a copy of the previous state and then we're going to add in one new um One new item to this object so the key for this will be the key that we've received and then the value will be the marker just like that all right uh hopefully we'll fix that air as we as we keep going um the next thing is that what if there isn't a marker so then we're going to do is we're going to take a copy so new markers is a copy of the previous ones with an equals here and then we're going to remove the one that's no longer there because it's null so we'll say delete new markers at Key and then we're going to return the new markers just like that and now because we've filled out the else we've fixed typescript okay so this is the error we need to happen uh we need to solve for uh maximum update depth exceeded this can happen when a component repeatedly calls set State inside of component will update react limits the number okay so basically this is being called way too many times and the reason for that is because we're rendering 500 markers and for each of those 500 markers it's going to call the call back ref function and that may be called multiple times maybe with null maybe with the actual mark marker and basically react to saying whoa you're you're trying to do way too much stuff so what we can do is just add in some safeguards here so what we can say is if we received a marker and we already have that marker in our object so we'll say markers at the key return we don't have to do anything we already have that in our state let's get out of there the the next scenario we need to handle is if there is no marker but that marker wasn't in our object anyways so not markers at Key meaning we have nothing to remove so don't bother updating the state anyways so we're just trying to say like only update the state if there's something to actually update if the marker is already in there at the key or there is no marker but there's nothing to remove anyways let's just get out early return and try to avoid calling this so much and then if we come back we're not getting that air anymore but we're still rendering out 500 trees but we have made progress because if we were to console.log markers and then we update our Dev tools you can see that we have a big object and that object is containing basically one entry for each of the 500 trees or each of the 500 markers if we open this up um you can see what each marker is and it's sort of hard to read so why don't we close that thing back up but we've got all of our markers inside of our state and now what we need to do is add an effect that we'll basically watch for whenever those markers change and tell the clust clusterer to go cluster those 500 markers together so use effect like this and what are our dependencies going to be on this one it's just going to be anytime our markers change so anytime the markers change what we're going to do is we're going to access the clusterer do current and because there's a chance this isn't initialized yet we're going to have to call it with a question mark so let me show you if you call it without a question mark So Clear markers it's going to complain and say it's possibly null so we can just add that and fix the typescript there so every time the markers change let's just clear out whatever the the the clusterer currently has and then we'll tell the clusterer to go add all of the markers we currently have so remember we're storing them at as an object where all of the values are the markers so what we need to do is say object. values of the markers to get access to all of the actual markers and let's see what happens so I'm going to close this so now we've taken our markers 500 of them and then we've added those markers to the cluster and then the cluster from that point sort of takes over and it's like I'm in control of rendering these markers now and I'll decide based on your zoom level if they should be clustered together or if we should show the individual Advanced marker so at this level we can see three Advanced markers and then in this Zone we got 32 so if we zoom in you'll see that we go from uh basically the all of them or if I zoom out I should get 500 at some point um and then as we start zooming in we eventually get down to where it feels comfortable to render out the actual markers so if we go in here we get these trees here and that allows us to sort of view things in a more manageable way and you can imagine if it was all over the world rather than just focused in Toronto you could sort of see where are the pockets of markers and then your your user can double click into those zones and um if you click one of these it sort of Zooms in to where it starts to break apart from a clustered marker into individual markers and that's how you take um rendering out your 500 Advanced markers which are these little tree emojis and then we've used the reference to the underlying actual marker instance because that's what the clusterer wants to receive it doesn't really know anything about about react it doesn't know about um raw Tree locations it wants actual markers so we need to access the marker we've chosen to store them in state as an object where all of the values are the marker instances and then anytime that data changes we'll use uh use effect hook to basically clear out whatever markers the cluster had read all of the new ones and then that will be in control of rendering this out on the screen and you may think and and I thought that so I tested it out 500 markers every time a marker changes this effect is going to run so we're going to clear out the markers 500 times that's not quite true so if we console.log um date. now we can just see how many times this is called and react is pretty smart about managing per performance so if we reload the page you can see that even though we've um we've essentially put 500 markers into state it actually only called this effect twice so react is sort of batching all of these uh set State calls together and it's it's controlling the amount of times that it rerenders then that it triggers a call to the use effect hook so really this is only happening twice even though we've done it with 500 markers so thankfully because of that react is pretty efficient and we can handle quite a few markers on our map hope you enjoyed that video this is how you can take a map using the new v.g react Google Maps package render out 500 Advanced markers as actual HTML so a span tag with an emoji inside that we can style and then take those 500 Advanced markers put them in state so that we can then pass them to the cluster so it can take over rendering and grouping them together in different ways thank you very much take [Music] care
Info
Channel: Google Maps Platform
Views: 9,464
Rating: undefined out of 5
Keywords: Google Maps Platform, Google Maps API Key, Google Maps Package, How to make Google Map, Making Google Maps, Advanced Markers, Cluster Markers, marker clustering, vis.gl framework, Vis.Gl, visualize big data on a map, big data on a map, react google maps, react maps, google maps react, Geospatial visualization data, open source, open governance, open data, React
Id: ZvoMak9yApU
Channel Id: undefined
Length: 25min 18sec (1518 seconds)
Published: Thu Dec 07 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.