Drawing our peripherals in React, take two
We learn an alternate, less hacky solution for creating an Axis component that lets React do all of the rendering.
This lesson preview is part of the Fullstack D3 Masterclass course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.
[00:00 - 06:04] So we just finished creating our access component and we used our D3 methods to draw our axes and let's talk a little bit about an alternative method for doing this and why it might be a little bit preferable. So if we use D3 to draw these elements it's feels a little bit hackier. React has all of these tools it uses to keep rendering quick and to prevent from re-rendering unnecessarily. It uses a virtual DOM and it diffs between that and the new render function to see if it needs to update the different parts of your app. And whichever framework you're using whether it's React or Angular or Svelte it's going to have these kinds of benefits that help preventing from unnecessary re-renders and usually there are reasons that it wants to know exactly what you're drawing to the DOM. Another reason is it's a little bit less declarative so if we're looking at this access component we don't know about all of these elements that are going to be rendered within our axis just by looking at the code and that can be frustrating especially to people who are less familiar with D3 who might also be looking at your code. So while it's really nice to have these methods available like access bottom and access left that do all this heavy lifting let's go ahead and see what it looks like to recreate these two functions using React and D3 is the utility library and after that just use your best judgment. Sometimes it can be nice and a pinch to have these kinds of methods for D3 and know how to use a rough to just throw them in and then maybe even change them later. So we're going to go back to our timeline and switch from our naive access to our other access function and it's going to have the same API where it grabs dimensions and the scale so if we go over to our access function in our chart folder it looks a little bit more complicated because it's going to be doing a lot of the work that D3 was already doing for us. So our access component isn't going to be doing much but deciding whether to render an access horizontal or access vertical. These are two separate components down here that will fill out and this just helps us keep our logic separate. There's different ways we want to transform and shift these elements that could be confusing if we try to do it all in one place. Alright so we're going to start with access horizontal which will draw our x-axis. So the first thing we just do is create those ticks that D3 was creating for us and thankfully we have our scale passed down here and each scale has a method called ticks so this is another benefit of using D3 where a lot of the functions that it uses internally to create those axes we can they're surfaced in the API and we can go ahead and use those for our own benefits. So let's just log out scale.txt to see what this looks like. So this is spitting out an array it usually aims for about 10 elements but aims for is the right word if it can round to better numbers and come somewhere near time it's gonna go with that instead. So you can see this is one date time for every week. So let's go ahead and create our ticks. Let me just call that ticks method and if we look at our chart right now it's gonna render too many ticks to handle kind of like we saw with our last axis the naive one. So what we can do instead is decide the number of ticks based on how wide our chart is. So we're gonna want the number of ticks and then we're just gonna pass that into this ticks function so it'll aim for a different number other than 10. So this is something I've done before so I know that if it's if our chart is less than 600 pixels wide we're gonna about one about one tick per 100 pixels but if it's wider we're gonna want about one per 250 pixels and that's just if you have a really wide chart you're not gonna need that level of granularity it gets a little bit busy. So we're gonna check if the width of our bounds is less than 600 pixels and if it is we're gonna return the width by 100 and if not we're gonna return the width by 250. So the next thing we want to do is shift our axis so here we're just gonna want to transform this transform and this made translated and we want it to be moved zero pixels left or right and we want to scoot it down for the height of our bounds.
[06:05 - 15:12] Boundted height. Alright so the next thing we want to do is to draw a line to mark the end of our bounds just to show exactly where that y-axis ends so down here we're gonna want a line and then we want to give it a class name axis line so we can style it with the CSS and for a line remember we want to set x1 y1 and x2 and y2 but it's going to start at zero zero and end at the width zero so we don't need to set x1 y1 or y2 because they're all gonna be defaulting to zero we just need to set x2 to the width of the bounds. So let's save that and see there we go so we now we can see that line and the beginning of our x-axis and the next thing we want to do is to draw the text for each one of these texts so remember these texts are each a daytime object so in our render function we're gonna map over each vertex we're gonna grab that daytime value object and also the index and for each of these we're gonna render a text element and for these text elements they're gonna need a key because in React you want unique keys if you're rendering things in a loop just so it knows how to keep them distinct from each other you're gonna want a class name let's call it axis tick and then we 're also gonna want to transform it off to the right based on the date time and the scale so we're gonna do transform equals translate and that's gonna be us we're gonna use our scale and pass in that tick so this is gonna return pixel value and then let's just render those real quick we're gonna want to just pass the tick in here but because these are each daytime objects this is going to render an object which React is probably going to complain about because you can't render an object it doesn't it just doesn't know what to do with that so we're gonna use we have this format tick function and basically what that's doing is that's a prop that we pass in with the access so if you go back to our timeline for our x-axis we're gonna want to use this format date function which is using d3.time format so it'll take that daytime object and return a I think that's month and then day so let's go ahead and see what happens when we pass that in there you go so yep now we're getting month and day and this is a nice way to keep your access components really flexible you can format these text however you want we could also automatically detect if we're looking at a daytime object and then do some standard formatting kind of like d3 does but it's nice to be a little bit explicit about it but in your components do whatever makes the most sense to you the other thing we want to do here is scoot them down a little bit because they're sitting on top of that line right now all right great the next thing we want to do is to add a label for our axis we it's nice to be explicit about what exactly we're looking at so we have label passed in as a prop we can see it's passed to our axis component but it's optional so we'll want to check if it exists first and then if it does exist we'll want to render a text element and inside of here we'll render that labeled text we'll want to set a few things here we can set a class name just for styles set it to access label we'll want to transform it so for x axis maybe it makes sense to have it in the middle of our x axis and then down below our x axis tick labels right here so let's do translate let's scoot it down by or scoot over by half of the width dimensions that bound in width divided by 2 and then let's move it down by about 60 we'll probably you know let's just add a label real quick to test so date let's see where they go so that's gonna sit right down here we actually don't necessarily need it just because when people see month and day they're usually gonna know that that's a date if you want to be more explicit if this were date the weather happened or something it would be nice to have that label there all right so with this all done why don't you try pausing the video and filling out this axis vertical and seeing how far you get just to just as a test to see which parts you need to look up so you pause it now and then come back all right so hopefully you paused it and tried that out we're just gonna walk through this code so this is gonna look a lot like axis horizontal where we want to grab the number of ticks we're just doing one for about 70 pixels you could change this whatever feels the best to you one per 70 pixels feels about good just from eyeballing it for me and then we create those ticks we create the line on the right side of our y-axis we just want it to extend all the way down and then we're gonna map over each one of these ticks we're gonna suit them left a little bit and also up based on our y scale and format those ticks note that our format tick function defaults to just a number format which adds a comma so you don't necessarily need to add a format tick function which we didn't for this y-axis and then we optionally render that y-axis label over here let's try just passing in let's double check what exactly are we using here so this is our temperature just temperature all right so let's go ahead and pass it in so now we can see our y-axis label is rendered over here all right so hopefully that was a good rundown for how to replicate those d3 methods using react it's definitely a little bit more work off the bat but once you have this axis component it's you can use it anywhere you need a react chart you can also customize it to your needs it's a little bit less hacky and d3 does nice things like surfacing the methods that you use internally and within its external API so we can use things like dot ticks to create ticks for our axes and it really isn't that painful so going forward you at least know these two different methods I definitely preferred this one but just use your best judgment whatever is easiest for you maybe you start with the hackier method and you move to something a little bit more customizable and less hacky as you have the time totally up to you