Create Highly Reusable React Components in Minutes with TypeScript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up in this video I want to show you something I learned recently to make your react components way more reusable this integrates really well with typescript however you can follow along in JavaScript just fine so let me show you what I learned how it can make your react components way more reusable and let's Dive Right In okay hey so we are in a Nexus 13 project and this is featuring the brand new app directory um not that it really matters this kind of framework agnostic as long as you're somewhere in the react environment right okay so the point is we have one custom component which comes from ad components and then the new Doc button which is this button right here and essentially what we want to do is turn this button into a reusable component that we can also style and customize from wherever we render it because that's the premise of a reusable component right that's the whole goal now previously if you're not too familiar with typescript you might do something along the lines of you know having a class name in here and then defining that class name in your um in your props that you receive for that component as something like a string for example now that works we can do that and now we can pass the class name like this so the button saying class name and now whatever we pass from the page as the class name something like background of red 500 would be rendered on the front end and shown on the button however this gets really confusing and hard to maintain as soon as you get multiple properties so let's say from the page.tsx we also want to control whether the button is disabled so we say this abled and that would by default be true because we passed the property then we would also need that in here disabled is an optional Boolean and then we can say disabled is equal to disabled that we also need to receive here from the props now that would work as well right same principle it would be disabled right now if we check the browser you can see the icon is a bit different we didn't specify any disabled Styles but the mouse is different so this button is currently disabled this is not the best approach to do it in fact it's I think the worst one you can take it might seem intuitive at first but um this is hard to maintain it's not really reusable in the sense that we want we have to Define every attribute that we want to pass to the button as a prop typing it out ourselves and that is not the point of having reusable components so the question then becomes how do we make this better and let's get to the solution part so that was the problem now let's get to this solution what we can do is first off let's remove all of this and now in the button component we can do something really cool because we're working with typescript we can say interface new Doc button props that we pass right here to the functional component you could type this out differently you could also have this as the new dock button props and leave away the whole FC thing that would also work now these don't contain anything yet that's why this is highlighted um I just chose to go the FC route but it does not really matter um just because somebody asked me in the past um which approach is better and there is no real better approach okay now how do we get the class name how do we get it disabled and so on let's delete that first let's remove these values so the better approach we can take is extending this interface so we can say extends and then we can say react.html attributes and in here we can pass something um and in our case that's going to be the button right so we're going to say HTML but button element and as you can see that works so essentially if you're not too familiar with typescript what we're doing here is saying we want our interface to also include every value that an HTML button element has by default so that is very interesting because now we can say um in the page.tsx if we press control and spacebar we can see for the autocomplete before it was just the custom properties that we had but now it's very different now we can pass all the properties that the react button gets by default right I mean most of these we don't need to worry about but essentially what that allows us to do is um to kind of tweak this component wherever we render it so if one instance we render this in the page.tsx and we want a specific attribute like area label oops label of you know page.tsx for example and then in another place we want the area label to be you know wherever we render that not that it would make any sense but we can Define all the attributes that the button normally gets now one kind of weird thing I've noticed is that some properties are missing for example the disabled right we could pass the area disabled but that's not what we want maybe that is what we want but in our case that's the disabled if we want to pass that doesn't fly right now that that doesn't work and what we can do is in this object right here Define all the custom properties that we still want in the button right so this extends um kind of ends here and in here is everything that we want to pass ourselves so only um custom properties go here so everything that we want custom goes in here and but by default we have all the elements inside the bot so if you wanted a disabled prop that would be an optional Boolean and we can say the button is disabled if this is disabled so we also want to receive that as the props right here and instead of having the really ugly disabled is equal to you know in in object notation disabled we can literally just pass disabled and that will work just fine and now we can get all the props that we pass from the page.tsx so let's say we wanted to pass the aerial label of button right we want to pass that right now this is not being displayed in our component and the way we receive everything that we pass is through the last argument being the props that we spread in and then here we can now say props passed to button like that let's log out the props in the console and see what happens um so whenever we render this component let's reload the page we can go back into our console and in here we can see what we've just logged out and I can make that a bit larger is the area label of button now if we were to pass anything else something like you know uh area busy is going to be equal to true for example I'm just passing random values here um just to see that they also get logged out in the button and the way we can then transfer them to a button is by spreading them in so we can say all the props that we receive from the page.tsx or wherever we render this component instance will then be spread into the button and thereby used in the button so what that allows us to do is also use something really cool like the class name so we can say background red of 500 specifically right here because in this instance we only want the background red if we render it on the page.tsx because otherwise if you always wanted that you would specify that in the button right here but let's say in this instance we want the background rate of 500 then we can go back in the browser and see okay cool that works just fine now um there is a better approach to the class name specifically so for example let's say we pass the class name instead of having it as the props spreading we can also destructure it directly and that means it's not contained in the props anymore but instead it's the separate property the class name that we've received right here and the reason we get no typescript error is because the class name is in this one right here that we are essentially extending the interface by meaning we have access to it with typescript and it also knows what the class name is as a string or undefined you know because of this syntax right here because we extended the element and now what we can do is kind of a best practice in my opinion and so let's say we want to pass the custom class name to the button what we can do is dynamically combine this so as you can see up here I've defined a utility function to merge Tailwind classes this uses two separate packages one is clsx the other one is Tailwind merge from Tailwind merge both available npm and essentially what we can do with them is conditionally render Tailwind classes so we invoke that function and then by default we maybe want to pass background red of 500 but let's say we also want to pass you know the cursor not allowed if the button is um you know is loading for example now this is loading property it's just an example um it doesn't exist so let me Mark that as loadings equal to false um but you know this would be dependent on your API call if the spot makes any API call and then as the final argument so after that we want to pass the original class name so that means our button will have default styles that we pass in as the first argument then conditional styles that we apply depending on some properties like API calls but also then as the last argument the class then we pass from wherever we render it so let's say we wanted a text of large I think that's yeah it's text okay so we can save that and then the text will be large the background will be red but we only pass the attacks large from right here because we append it to the conditional class name and that's kind of out of screen that looks a bit weird I should probably adjust my prettier but I think you you get the gist of it and essentially we are doing the conditional rendering that we're just marking with a constant and then appending the original class name to allow for default styles of the button and then custom Styles depending on wherever we render it now obviously be careful what you pass as the class name because this should be a reusable component that looks similar in all occurrences but this is a best practice I want to show you just extending the element and then handling custom classes like this I think it will make your code way more maintainable way easier to read and just an overall better practice to implement in your react projects okay that was all I want to show you thank you very much for watching and congratulations on your cool new reusable components I'll see you in the next one and bye
Info
Channel: Josh tried coding
Views: 9,563
Rating: undefined out of 5
Keywords: best practice, class variance authority, josh tried coding, joshtriedcoding, react, react best practice, react best practices, react best practices 2023, react best practices components, react best practices folder structure, react typescript, reactjs, reactjs typescript, reusable, typescript
Id: BKFPfzWM3CQ
Channel Id: undefined
Length: 10min 35sec (635 seconds)
Published: Thu Feb 16 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.