Functional React With Styled Components
with Shaundai Person
Learn how to create clean, beautiful React UIs! Shaundai Person will teach us how to combine function-style React components with Styled Components.
Resources & Links
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
Jason: Hello, everyone, and welcome to another episode of Learn with Jason. Today on the show, we have Shundai Person. Thank you so much for hanging out with us today. How are you?
Shaundai: I'm great. How are you, Jason?
Jason: I'm doing so good. So excited to have you on the show. I'm also just excited because every time I meet somebody who has their own name as their Twitter handle, like no end initial or anything, I'm just like, man, I'm in the presence of a celebrity here.
Shaundai: It's like you think Beyonce, you think Shaundai.
Jason: (Laughter) Exactly. Well, so for folks who are not familiar with your work and why you deserve just a name, can you give us a background on yourself?
Shaundai: Yeah, so I am Shaundai Person. If you get confused, I think of it like a day of the week -- Friday, Saturday, Shaundai. I'm a UI engineer at a company called SalesLoft. We build software for salespeople, which is serendipitous because I'm a career switcher. Last year I decided to switch careers. I was in sales for 12 years. I made a leap to something I was passionate about, which was engineering. So I sold software at SalesLoft and taught myself how to code and made the switch into building the product.
Jason: Fascinating. So you're a career switcher inside of the same company.
Shaundai: Inside the same company.
Jason: That's super cool. I think you might be the first person I've heard make that -- like usually I've heard of people who, you know, they were doing a thing and then they learned to program and joined a company that overlaps their skill sets. I love this story of actual lateral growth like that, where you don't have to leave your job to get into a career that sounds more interesting to you. That's amazing.
Shaundai: Yeah, it was scary, and it was a leap. So I'm a mom, too, and I'm a mom to a 3-year-old. So sales is something that's secure. People that are in sales in general are doing it for the money. I was good at sales, and it had been my career and what I saw my career trajectory going, you know, sales management or sales enablement. So it was a leap. You know, I consider it a lateral move, but some people might say because I was starting at the entry level that it might have been a step down where I already had this credibility built as a salesperson. Now I'm going into kind of an entry-level type role or level in engineering. But it was something that I was truly passionate about. Like I would spend my nights -- I gave myself half an hour a night to learn to code. Then it would turn into four hours, five hours. I'd be up until like 1:00 a.m. So I was like, listen, I can make money doing engineering, too, but I could also love it.
Jason: Yeah. Well, I mean, that's amazing. I love those types of stories. It really -- like I repeat this phrase over and over again. Play until it pays, which is kind of find something that's interesting and chase it and then find a way to make that into what you do for a living. I think that's not always practical, but I love it when it plays out like that, when you can just be curious and let that curiosity guide you towards something that, you know, that can be a fulfilling career. So I'm so super happy to hear that worked out for you.
Shaundai: Thank you. Thank you. Happy to be here, part of this space. And with you.
Jason: Of course, of course. And what's up, chat? I see a lot of familiar faces. I see Nicky out there, Linda, Luke. What's up, everybody? It's good to see you all here. Thank you for coming and hanging out with us today. And why are we hanging out today? What's our plan today?
Shaundai: We're going to Reactify today. It's Earth Day. Happy Earth Day, everybody. We're going to Reactify everything. What we're going to do has nothing to do with Earth Day. I don't know why I'm talking about it so much. Functional React.
Jason: Yeah, so I'm super excited about this. I feel like I get asked kind of -- like I talk about React a lot. React it a big part of my day to day. But functional react, this idea of classical components. That's an interesting conversation because I don't think that we -- we talk about it sometimes, but what is the benefit, would you say, of choosing one versus the other?
Jason: Right after my own heart. I very much feel that. Like, why make things hard? I joke a lot about voluntary suffering, and I think that a lot of programming is built around this idea of voluntary suffering. Let's make this hard so that we can prove that we're smart or whatever it is. But I really do like the way you describe that. Actually, I had a conversation with Sunil Pi, who used to be on the React team. He's off doing other things. We actually had him on the show recently. I'll drop a link in the chat. But he did this really interesting visualization when hooks came out of how context was grouped in class-based components versus functional components. What he did was color coded it. This color for state, this color for what the UI looks like, this color for other things. Then he took a class component and showed the color was all mixed. Each line was different colors. Things were weird. Then he moved it to hooks and the colors all grouped. Everything was suddenly contextually grouped. You could see where everything was happening. I thought that was such a brilliant way to show how hooks clean up React code.
Shaundai: Amen to that. Like, that's -- 100%, that's my life. I want clean. I want my colors organized, metaphorically speaking.
Jason: Color code everything, always.
Jason: But yeah, so then the other thing that we were going to talk about today is styled components. Styled components can be a little bit of an overloaded term. I see a question in the chat already. Are we talking about a flavor of styled components or the library called styled components?
Jason: Great. I mean, I'm into it. So I guess this might be a good point to actually start looking at some code because you're describing it, and I'm interested. I want to see how it works. So let me switch over into the paraprogramming view here. So this is Sunil. He did this mock-up. But we're not talking about Sunil. Let's talk about Shaundai. Go follow her on Twitter right now. Go make that happen. Go get that follow in. While you're at it, make sure you go and check out the Learn with Jason website. We have, as always, live captioning happening. We have Rachel with us today. Thank you very much, Rachel. She's from White Coat Captioning. And that is made possible by our sponsors. We've got Netlify, Fauna, Auth0, and Hasura all making this show more accessible to more people. If you want to follow along with the captions, you can do that right on the home page of learnwithjason.dev. And don't forget, these are linkable. Check these sponsors out. So today we're talking about React specifically. Let me drop a link in the chat. Then we're talking about Styled Components. Here's the homepage. So I'm ready now. You've got me sold on this. I want to write some functional React. I want to do some Styled Components. If I want to get started, what should I do first?
Shaundai: So the first thing is to open up your VS Code or wherever you're writing your code.
Shaundai: Actually, yeah. We can open the terminal too.
Jason: Oh, my, I can't type. Third time's a charm.
Shaundai: Sorry, I should have said the first thing to do is to install create React app. We're going to use a tool for putting together our React code. So let's go back to the ancient times, back before Create React app existed. It took a lot of stuff to put together a React file that works in the browser. So little known fact, React doesn't right out of the box work in the browser. You need different things to make it work and to make it function in the way that it should function. So Create React app is this tool that allows you to just put in one command in the terminal command line and have all this stuff packaged up beautifully and ready to go. So we'll use Create React app for this.
Jason: And in the chat, somebody found Sunil's post. This is a class-based component. So you can see there's context, there's data, there's styles, more context here. Then when we switch this over to a functional component, you can see these -- the context groups up, the data groups up, the style groups up. Suddenly, you've got a nicely, you know, contextually grouped set of code. It obviously also just gets much shorter, right. Like it's a little easier to read. So I think that's a pretty beautiful comparison of the two styles and why this move was a good move on the side of React. I think hooks gets a little flak these days because -- a way I've heard it described that I like is it takes what used to be hidden complexity and brings it right up to the front. That, I agree. Sometimes I don't want to know all my stuff is broken. (Laughter) but it's probably better that we do. Okay. So I have Create React app. If we want to get started, I can run this right here?
Shaundai: Yep. So let's just copy the first part.
Jason: I'm going to put it right in this folder, using the dot like that.
Shaundai: Yep, so this command is what's going to create the file. The next thing is going to be the name for it. Or in the documentation.
Jason: Yeah, so this is saying, like, it's going to create a folder called my app. Since I put in a dot, I already had a folder, and I'm going to have it use the folder I'm in, which is this one here, react and styled components.
Shaundai: We are cooking.
Jason: And here we go. All right. I see the chat has rediscovered flappy Jason. Does functional mean hook? That's a good question. (Elevator music)
Jason: Just got that going full blast today.
Shaundai: I don't know. I don't know the answer to that. We can look it up.
Jason: So I do know the answer to that. The difference is when you talk about functional components, you're talking about writing them as functions. Hooks make functional components more powerful, but they're not like required. You can write a component as a function. That's what we used to do for stateless components. I've heard them called dumb components. But if you didn't need state, you could not write a React class. You could just write a function, and it was simpler to read. But then it would lack all of the class life cycle hooks. So what hooks did was let us write class style logic inside of functional components. But they aren't -- like, you don't need to use hooks to use functional components unless you need to use state and don't want to convert it to class.
Shaundai: I see what the question was, yeah.
Jason: But that's that. Let's see here. So we've got ourselves a site. Let me pop this thing open. So first and foremost, we have installed kind of a basic app here. I'm just looking at what we've go the. We've got the React scripts, the React core, some testing so that we can test this thing. And web vitals around performance. Some basic scripts. Okay. This all seems like what we want. Then we've got our source here and some public stuff. So these are all -- that's a favicon.
Shaundai: Yeah, so like I said, it gives you everything you need to get up and running. The public folder is just -- so web pack -- I forget the term for it -- a module bundler or something like that. What it does is it takes all of the dependencies and things -- the stuff that was in your JSON right now and gives it to the browser in a way that the browser can understand it. So what it passes to the browser is something different. Everything in the public folder is stuff that the browser -- or sorry, that web pack doesn't need to touch. So you don't really have to worry about too much of the complexities of how to manipulate this or what to put in public. But some things to know is that like the favicon is in there, which is the little icon in the tab browser. That's there. Yes, exactly. And your index.html file is in there as well. So one thing to note about Create React App is it allows you to easily create single-page React apps. What I mean by single page is that we are essentially just displaying in every one of these apps or every app created from this Create React App, just one HTML. So the way I think about it is HTML is like the skeleton or the frame of the house. Then we will paint it or repaint it with React and some styles. So the reason for React is it's a lot faster. You don't have to -- like if you click to -- click a button and the background changes, you're not rewriting the entire frame of the house. All you're doing is repainting it so it just happens like that. You don't have to flip to another page. So you may be used to building out -- like an index.html page and about.html page and you have to have separate stylings and separate JS maybe. This is all just getting rendered from the same one HTML, which has a link. And we can go -- I think it's down toward the bottom of the same HTML file, sorry. Yeah, so we're linking -- there's a div with this ID root. That's what we're linking to our JS. So all of our React files are going to be connected with this ID root.
Jason: Right, yeah. Because we're grabbing it here.
Shaundai: Exactly. So this index.js is the parent of all of the React components. I think in metaphors, so bear with me. I'm not technical by trade. This is for my sales people out there. This is like the family lineage. This is like the grand mack daddy. This is the component that sits in the big armchair. He gets the big piece of chicken. He walks around with no shirt on. Like this is the daddy of all of the other React components. So everybody, all of the other components are just part of this family tree, and they stem from this is app, index.js. Okay? So this reactdom.render, it's the HTML, the dom, like this mystical, virtual world. This is where we're doing all the painting -- I'm sorry, Jason.
Jason: This is so good. I also mostly think in metaphor and analogy. So this is so in my lane. I'm so happy I'm not the only one who does this.
Shaundai: I sit up at night thinking about how is this like a unicorn? I sound so silly -- yeah, learn the technical terms for stuff, but I'm going to explain it, and you'll understand it and you can find out the technical terms that match it. Reactdom is the frame. This is where the skeleton is. This render is a function that takes two arguments. First argument is the element. Second argument is the container. So you have your cookies, and then you have the box the cookies go into. The app is what we want to put -- stop laughing. The app is what we want to put inside the container. And this document.element.id, that's where we want it to go. So essentially, to explain it a third time -- sorry -- we have the frame. We want this app component to be painted on the frame.
Jason: Yes, absolutely.
Shaundai: That's what that is. Okay. So we've got the granddaddy. This is not the one we're going to change. The one we're going to change is the child of the granddaddy. This is the mama one. This is app.js. So let's go into this one. This is a functional component already. Already two different ways that you can render a function component. Some people favor this way because we're using the word function. Then we'll say the name of what the component is, put the arguments inside these parentheses, and then open the curly brackets to put whatever functionality we want to in there. My favorite way of doing it is to declare it like a variable. So this may also be called like a fat arrow function, but the first thing that I do with this component in particular is just kind of blow it up. So what we're going to do is take the function keyword, change that to a const, and after app, we put the beginning of an arrow and then after the parentheses, put the rest of the fat arrow. Okay. And we have a component that works pretty much how it used to before. So this is the main thing. It's really a matter of personal preference in what you decide. The reason why I like declaring it as a variable is because I think it looks cleaner. This is just, you know, my own personal preference. I like to see the uniformity of all my variables in my functions to just start with const. Like I said, some people just like to see that actual function keyword and know right away that this is a function. But this is what we'll be working with today.
Jason: Yeah, no, this is great. And like you said, it all comes down to personal preference, right? Because functionally, this is equivalent to the other one, but really, it's whatever makes you feel like you like the code you're writing. For me, it's always a matter of consistency. I don't have a preference of const over function --
Ah, son of a biscuit.
Jason: What? What happened? Oh, you're mad because the dumpster fire is not me anymore? I watched you, chat. I'm just trying to ignore you. But yeah, so we've got -- you can use the function style, the const style. Just keep it consistent. Make sure your co-workers know what they're getting into when they dive into this code. So then down here, we export that so that we can get it here.
Shaundai: Yeah. And there's a number of -- not a number. There's two ways that you can -- or three, I think. There's two main ways that you can export it. If you want to try something different, you can leave it as it is right now, or instead of the export at the bottom the way that it is, one way to do it is to get rid of the export default app at the bottom and then we'll just add the word export before the const when we make that declaration right there.
Shaundai: The difference now, though, is if you go back to your index.js file is we need to add curly brackets around the word app because we're exporting it as -- I think the term is a module.
Jason: A named export. Like it's now named instead of a default.
Shaundai: Okay. You're right, Jason. I was testing you.
Jason: (Laughter) Yeah, no, actually, this is one of the things I really like about the new syntax. This type of flexibility is available. In the ancient days, as you called them, when we had to write common JS, where everything was like using require and you had to do like module.exports and stuff, that was a huge pain because we were writing node code for the browser. This, this is ES modules. This is web native. So these days, if you weren't using JSX, because that doesn't work in the browser, you could ship this much React straight to the browser without transpolation. You'd need to write this with the JSX style function, which I don't recommend because it's not a lot of fun. Yeah, so I'm into this. But so I can already see one thing that we talked about, which is you're not a fan of this here, this .css.
Shaundai: That is correct. So this is bringing us back to our point where you need a separate CSS file, and then if I wanted to test this, I'm adding a third file for the same component. So we're going to blow it up as well. So we can just -- let's just get rid of the export -- how do you want to -- do you want to just ignore the app.css or just delete it?
Jason: Let's delete it. Get it out of here. Let's do this, though. Let's get this thing running so we can see what happens as we go. So if I can remember what the command is -- we're using yarn. It's start, I think.
Shaundai: Yep, that's right.
Jason: This will give us a dev server. And it opened in the wrong window. How dare you. Okay. Over here.
Shaundai: Wow. Disrespect.
Jason: Indeed. So what we had before is when we have this style, this is what the page looks like. So I'm going to stick this one to the side. We'll stick this one over here. Then when I get rid of this, we now no longer have any styles. So everything starts to get a little squirrely. But we can also do things like, hello, and it reloads really fast. This is one of the things I really love about Create React App, just how quickly we can see things happen.
Shaundai: Right, yeah. So everything is in real-time. If you're one of those instant gratification type of people like me, this is a great way to test and figure out what's going on. You can see instantly when something breaks, and you'll get a nice message that says it's broken.
Jason: Yeah, let me break it, and let's do that on purpose. And it even shows us what's wrong. That doesn't look right. Let's fix that. I see we're testing how long the beard goes. You can grow it off the screen, y'all.
Jason: Okay. So then -- now, we've deleted our app.css. Or we're not importing it anymore. So at this point, I think we need to -- do we need to install Styled Components?
Shaundai: We do, yeah. So we can -- let's go to the documentation. I know it by heart, but I want to show you where it is.
Jason: Documentation. Probably installation.
Shaundai: Yep, installation.
Shaundai: Then it will be -- yes.
Jason: I'm going to grab -- yeah. We're using yarn, so I'm going to grab the yarn one. Let me do that. Nope, not that button. This button. Oh, my goodness. Try that one more time. There we go. All right. So we're getting Styled Components added here. Once that's in like that, I will start the server again, and let's see if it's going to use my same window. I think it will. It did. Okay. That's one thing I really like about Create React App. It's smart enough to keep the tab, so it doesn't keep opening new windows. That makes me really happy.
Jason: Now if we look, I've got Styled Components.
A-ha, behold! My bucket!
Jason: Indeed. (Laughter) Now I'm ready.
Shaundai: Great. Okay. So the first thing you'll do is import Styled Components. You'll need to do this in any file you're going use CSS in JS or where you're using your stylings.
Jason: Let auto complete do the work.
Shaundai: Beautiful. This is great. Amazing. So now we can add some styles. So let's just play with it. So let's change the background color. The way that you'll use Styled Components at a very basic level -- and this is up to you how you want to do it. I'm giving you the way I do it. So on line three, we're going to do this before we do our function declaration and all that good stuff. You could do it after. It'll still work the same way. So we're going to do const like we're naming something. So we're going to replace the div. Let's do capital D div, is what we're going to name it, equals styled. --
Jason: Oh, look at the auto complete. And I'm going to make an assumption we want a div.
Shaundai: We do. And then we'll do the back ticks. So do two back ticks. Okay, perfect. So what you're looking at now is we have declared a variable called div. We're going to use the capital D because we don't want to -- and this is the same thing with your React components. You need to use a capital letter because HTML are all using lower case letters. To avoid having confusion between the browser and your brain and your app, you need to use capital letters for -- this is really a component. So we want to use capital letters for all components. You can call it whatever you want to. So this could be capital D div. It could be capital D dog, whatever you want it to be. What's important is you use the word style, and you'll tag it to whatever HTML element you're using to replace it. In this case, we're going to be replacing it with a div -- or replacing a div with capital D div. So we want it styled.div.
Jason: Then I just drop this right in, right?
Shaundai: Yep, exactly. Now we have a styled div. So they're linked together.
Jason: And I saved it and nothing happened, but that's to be expected because we haven't added any style yet.
Shaundai: Exactly. Now we need to add some style. So let's do a background color.
Jason: And do I just write plain CSS in here?
Shaundai: Plain CSS, exactly.
Jason: What's our background color? What's your favorite color?
Shaundai: Pink is my favorite color.
Jason: Okay, yeah.
Shaundai: This is pretty. This is like a work of art.
Shaundai: I mean, I don't know. I'm getting a little misty eyed. This is pretty good. So you can add any type of styling that you want in here. Let's make a high of 100.
Oh, right. That's exciting.
Jason: Sorry, what was the --
Shaundai: It's a beautiful thing. Yeah, so it looks really good. Let's add some more stuff. Let's center it. Let's center everything. Display flex. This is my magic trick. Display flex and flex direction is column. And justify content -- yes, content, center. And align items center.
Jason: Beautiful. Look at it go.
Shaundai: Yeah, so we put everything in the middle, guys.
Jason: And also, I will say --
Behold! My bucket!
Jason: Indeed. We just vertically centered something in CSS, which I know is an old joke, but I actually do like to point it out whenever it happens, that this is how far we've come, where you don't have to like do anything wild. You can just say, I would like this to be centered, please. And it just works.
Shaundai: Yeah, yeah. And when I was first learning -- I know flex had come out before then, but I hadn't learned it yet.
Hackers. You dirty, dirty hackers.
Shaundai: I was like, add a little helper at the top. Make sure it's the same size. If people scroll down, God forbid. It just got so chaotic. So these three or four lines of CSS, it's present in every single app that I build. Okay. So we centered a div. Same situation if you're trying to do like IMG header or anything like that. Just tag whatever HTML element it is with the styled tag.
Jason: So we want to make this image. We'll do a styled.image, and then I can -- let's say we want to give this like a set width of, we'll say, 20% of the screen. Then -- actually, that's probably enough to start, right? Then I can just swap this right on out.
Shaundai: Yeah, so you're just replacing the tag.
Jason: And it does the thing. So let's make it bigger. Look at it go. I mean, that's great, right? How great is it that we can do that sort of thing? Then I can also give it a height of 20 -- whoops. What's going on? There. Okay. So my -- I don't know why it doesn't like my actual width. It's like my background is doing something weird. It's okay. Everything is fine. Oh, you know what I bet it is? I bet they have some empty space on it so it doesn't smash against the side of the screen.
Shaundai: Oh, like a little bit of padding or something.
Jason: Okay. We can make it bigger to accommodate for that.
Jason: Hey-o. Beautiful.
Shaundai: Awesome, awesome. So yeah, and I think this looks shippable, basically, right now. And I'm glad you did this one because you can see that even on the image, we're still giving it the same prop. So it's extending all the same image props that an image has. The SRC, the class name, and all that good stuff, the alt. All the same. The only thing we're replacing is we're turning this into a component now, a React component, and now we're able to just use our CSS styles and extend those in here as well.
Jason: Yeah, for sure. And I can see how this does get kind of nice if we're talking about the image that we were looking at from Sunil where you see the color coding. Now we have this big color block of styles. Then we've got markup down here. We don't have the mixture of like doing in-line styles, which -- and there's no problem with that. There's a lot of good things to be said about things like Tail Wind. There's a lot to be said about pulling it out to CSS modules. You can do this any way you want. This all comes down to personal preference and what you and your team decide are the best thing. So this isn't -- nobody is telling you what to do. Do what you like.
Jason: Okay. So here's our basic button.
Shaundai: Yep. So all these styles are just the basic, you know, whatever HTML gives us. So let's add some basic styling to the input. So let's change that to a Styled Component. We're going to call it whatever you want. Let's say input. Tag the input. Awesome.
Jason: There's that. Then I can do the same thing for button. So I'll do a styled button. And chat, I see your questions about using this other places. We'll have a chance to do a little bit of that shortly. So stay tuned. Okay. So we've got our styled button. Now you were saying you wanted to do some dynamic stuff with this, which I'm very excited about.
Shaundai: Yeah, so let's first add -- let's just add some basics. Let's give it a color, like green or something.
Shaundai: Sorry, the button, the button. Background color is green.
Jason: Oh, we're making this thing pretty. Oh, no. That's not what I meant to do at all. I meant to do border none. Okay.
Shaundai: This is so sexy. Let's make the color white.
Shaundai: Beautiful! Okay. Sorry if I get really animated. I have a 3-year-old, so I'm just like, you did a good job! This is great!
Jason: I live for it. Yes, please, validate me.
Shaundai: Yay! All right. I love it. I love it. Okay. So we've got our button. Now, let's say we want to -- okay. I'll show you this first. Let's say we want to make a second button. The use case for this, right, so at SalesLoft, the team I'm part of builds our component library. For those who aren't familiar with a component library, you're working on a giant platform, right. Marketing comes out with all these beautiful styles. This is what our buttons are going to look like. They're all going to be green with white letters. That button is going to be used in a million different places in the app. It may be used just exactly like this, but there may be scenarios where it's an icon only button or maybe it's just a different variant of it where it's a red button because it wants to tell you this is not allowed. But essentially, it's all the same thing, right? We build the component library where all of that stuff lives. So any other engineers on our team can just pick from and say, okay, I want this button. Add in a number of variants, and use it wherever they want instead of rebuilding it. So it's really good when you get things that are complex. Like we have a calendar, a date picker. Instead of having to do all that lift of building that from scratch, you just pull it out from our component library, import it into whatever you're building, and start with this nice foundation.
Shaundai: So let's say we're building a component library, right. We just started with our basic button. This is what our button is going to look like. Any other engineers can use it. So let's say another engineer wants to use this same button, but they want the color to be blue. So let's just copy and paste this entire button function thing. Sorry, Styled Component. I'm going to start being more technical. Then we're going to change the name, blue button. Yeah. So we're going to add to line 24, after the word button -- so styled.button. Add some parentheses before the back tick and put in the word button.
Jason: Do I need to quote it or anything?
Shaundai: Sorry, capital B button.
Jason: Oh, interesting. Okay.
Shaundai: So how we talked about extending the styles for the image, right, but we're still using the same properties, now we're extending the properties of that capital B button on line 17.
Jason: So I don't need this anymore, do I? I just need the thing I'm overriding.
Shaundai: Exactly, yeah. So you're extending the border, the color, and all that stuff, but the background color will change. So let's put the button in so we can see what it looks like. And it's going to be called blue button.
Jason: So we can put another one of these in but say blue button.
Shaundai: Let's put the text as like -- yeah, something different.
Jason: Oh, no, I've done something wrong. What did I do? Default.button is not a function.
Shaundai: What did we do wrong?
Jason: Is it just styled without the .button?
Shaundai: Oh, yeah, sorry. It is.
Jason: Cool, yeah. Hey! Look at it go!
Shaundai: Awesome. Awesome. Yeah, I like seeing -- I like to make mistakes on camera so that people can see that even Shaundai, even Beyonce's sister is not perfect.
Shaundai: Now you guys know the truth. Okay, so we did it. We made a blue button. This is our first extension of our component library. So we're cooking. Okay. So now let's add some dynamic properties. So let's say that this is -- it's going to change color depending on what's in the input box. So what we're going to need to do first, probably, is add some state to the input box.
Shaundai: And be able to figure out -- have the system be able to figure out whether or not the input box is empty. So let's say if it's empty, we want to disable the button. If it's not, then we want to disable it. We won't make the functionality work. We just want to color it blue, okay.
Shaundai: So we'll -- let's start with bringing in state. So we're going to use hooks now. So go to the top, and we'll import use state. And it's probably worth explaining like props and state, right? You think?
Jason: Yeah, it probably doesn't hurt to give it a quick minute.
Shaundai: Okay. All right. So -- I'm trying to think of a metaphor. Okay.
Jason: I'm so ready.
Shaundai: (Laughter) I got it. The React family, right. We have the granddaddy. We have the mama, which is our app. There are different things that I can pass down as the mother app. So this is the parent versus the child, okay. We are separate components because we're separate people and can only do so much. Same thing with components. They can only do so much. They should only have so much functionality. It's really an art, not a science. But the way I separate my components is I just want one component to do one thing. If you are the parent component, you can pass things to your child. Those things are called props. All right. So I am the template. I am this app declaration on line 28. I can pass things to my child. I can pass features. He's going to have curly hair. He's going to have chocolatey skin. He's going to look cute because he gets all this from me, right? I'm going to pass all that down to him, but -- and that's natural. But if I want to change anything, if I want to add any props -- and let's say he has dimples. I don't have dimples. But I want to pass that down to him. I can pass it down as a prop. So I can pass that down, but he can't pass dimples up to me because I'm the parent. So I can pass props parent to child. Did it all make sense?
Jason: That was -- you know, I honestly was like, how are we going to bring this one home? You nailed it. You stuck the landing. It was perfect.
Shaundai: Props. That's the word. So I can pass my props down to my baby. He cannot pass props to me. Parent can pass it to child, child cannot pass it to parent.
Jason: Yeah, that's it. Yeah.
Shaundai: State is something different. State is like my emotional state. I'm happy. I come in and I'm happy. That would be the state that I start with. I can pass the state to my child. I can pass happiness to him. I can give him candy and he's happy. He can also -- he can have a function that manipulates my state. So he can throw a temper tantrum and make me angry. He can make my state to angry, just like his state is angry. If he wants to change that for any of his siblings, he can go through me and change state as well. He can make me angry, and I can pass that state to another.
Jason: This is so good. This is truly outstanding.
Shaundai: Do you love that?
Jason: So good.
Shaundai: I'm going to write a speech on that, man. All right. So that's props and state. For anybody who's not technical, hopefully that helps.
Jason: Nicky wants to know, does React strict mode help with tamper tantrums? (Laughter)
Shaundai: I love that. I think it creates more. But yes. So good. We can keep going. The React family. I love it. So we'll keep this analogy going. What we're going to do is set state, right. So const, this is the way that you -- this is the syntax. So const. Then it's an array. The first part of the array is going to be the state, not the actual state. This is what we're calling state. Yeah. That's cool. Oh, sorry. What are we changing? The input value. So let's call it input value. Input, camel case. Input value is going to be our state. The second element in the array, so we'll do a comma, is going to be the set state function. So this is the name of a function that we'll use. So remember, I said my son can change my state. This is the function that he's using to make me angry. This is the temper tantrum function.
Jason: Got it.
Shaundai: The common syntax is set. Then the name of whatever the state is. So set input value.
Jason: Set input value. Okay. Then this is the result of this function that we just imported?
Shaundai: Yes, this use state hook. So use state is what your starter state is going to be. For me, in this case, it was happy. But we don't want this to be anything right now. This is our input value, and we just want to leave that blank.
Jason: Leave it blank, okay.
Shaundai: Yeah, let's leave it at that. You could put maybe some parentheses or something.
Jason: We could make it like an empty string since it's going to be our input value. We want it to be empty by default.
Shaundai: I like that, yeah. Let's go with that.
Jason: Okay. So we have a value. How do we make this -- because right now it's not showing. Like if I save, it doesn't say anything. If I made this, you know, happy, so how do I actually get this in here?
Shaundai: Right. So we're going to need to create a function that handles this input value or is able to understand what's inside of it. So on every input, the basic HTML, there is -- and I don't know the technical term. You guys could probably expect that. It's called e.target.value.
Jason: Oh, the event, yeah.
Shaundai: The event, yeah. So there's a method on it that we can pull in to our function. Basically, what we'll be doing is saying that if e.target.value changes or if it exists, we're going to change the color.
Jason: Okay. So I've got my E, my event. Then?
Shaundai: And yeah, let's go back to the arrow function syntax. So --
Jason: Oh, I got you.
Shaundai: Yeah. Again, it's a matter of personal preference. We could have did it the same way, Jason, that you were going to do it. Let's stick with what I said.
Jason: Yep, stay consistent.
Shaundai: Okay. So we'll handle change. On change -- actually, before we go through and add some functionality to the button, let's tag this with -- let's connect it with our input. So on the input, there is a prop, a method called on change. So what that's looking for is any time the function changes, or any time a change happens within this input, it's going to call this function. So we're going to set that equal to the handle change.
Shaundai: Beautiful, okay. And then let's see. So what we want to do is identify whether or not there's anything inside of the input. So let's say -- and I had some colors already picked out that I wanted to do. So, okay, cool. Let's say that any time this changes, we want to set the state, the input value, to whatever the e.target.value is. So we're going to call in that state handler.
Jason: So we just want to set it straight up. Whatever the target value is, we want to set this.
Shaundai: Yeah, yeah.
Jason: Okay. So then to get the value to show up in our input, because right now I think it's doing it, but is it in the state?
Shaundai: It's not going to -- yeah. We can link it up if you want.
Jason: Because I think what we can do is if we just set it like the value equals the input value, then when we type, it should be there. Also, in we set it to happy, it starts as happy, and we can edit it around. Then I think, too, if we -- actually, let's just log this, right? Let's console.log the e.target.value. Then we can see as we type -- hey.
Jason: Oh, wait. But I did something wrong. What did I do wrong? Changing an uncontrolled. Do I have to use initial value, chat? Is that what it is? Now is it going to stop yelling at me? Changing a controlled input to be uncontrolled. What? What? Default value.
Shaundai: Oh, I see.
Jason: Let's clear this. Let's just refresh this.
Jason: No more yelling!
Jason: Okay. So that's me just forgetting how everything works. But by doing this now, we can set it to be our default state, which I am very happy about. Okay. So now we have this. We have our values. It's updating the way we want it to, which makes me happy.
Jason: Like a ternary.
Shaundai: That's what I was thinking. And you don't even actually have to put the .length. What it's going to return is a true or false. So we say -- what it's asking is if input value exists, question mark, the first thing is what happens if it's true. The second thing is what happens if it's false. So let's put in one parentheses. Sea green if it's true. Then a colon, and we'll put black. Let's do that if it's not true.
Jason: Okay. Oh, I screwed something up. We have to get the input value. So is that in -- we have to get the props here, right?
Shaundai: We do have to get the props, yes. So what we can do -- I have the documentation pulled up, too. I think we can do props and do an arrow to it inside of the function.
Jason: Oh, like this?
Jason: Okay. So then we need to pass this down?
Shaundai: Yes, to the button.
Jason: So if I do input value equals input value --
Shaundai: You got it.
Jason: Why are you yelling at me? Oh, you're good. You're fine. Okay. So now it shows black, which that's good. That means that our code is doing what it's supposed to. We don't have an input value. Now if I say something, it's green. If I delete it all, it's black again.
Shaundai: Beautiful, yeah.
Jason: All right. Hey!
Shaundai: We added some functionality. Right. So again, sorry that was so confusing. So if it's true, that's what this function on line 18 is saying. If therapy input value exists, it's going to be sea green. Then if there's nothing in there, we're going to disable it. Really, we're just changing the style. But it's going to be black. Okay.
Jason: Yeah, no, that's great.
Shaundai: It has dynamic properties to it. And you see that the other button still didn't change. So the blue button we made doesn't change because the level of specificity, which is CSS uses these rules of specificity to determine what styles are actually rendered in the dom. This declaring it as blue button and overriding the styles, this makes it more -- like these are the number one rules for it.
Jason: Right. So now this one we overrode the background color. If we take our regular color here and we say, like, instead of making it, it'll be white then, but we can make it gray otherwise. So now we can see that it did inherit there.
Shaundai: Yeah, and type some text inside of it.
Jason: But we're not putting the initial value into the blue button. So if I do this thing, ta-da! Right, so you can inherit that logic. It's just whether or not you want to.
Shaundai: Exactly, yep. Yep.
Jason: Okay. So I'll put this back so that we don't have that -- oh, no. What have I done? Oh, you don't quote it because it's not -- okay. Look at that go. I mean, this is beautiful. I love, you know, the kind of -- the proximity you get with this, where you can see, you know, I'm in my component. I can see what's happening. How do you control for -- because I can see here we've already created quite a bit of components. You mentioned that at SalesLoft you're using these in a design system. How do you keep these from getting overwhelming?
Shaundai: We would make another component. So we can break this up into another component. Let's do that so you can see what that looks like. Yeah, you're right. It is getting kind of crowded. So we'll make a child.
Jason: Okay. So I'm just going to create a new file. Then what did you want to split out?
Shaundai: Let's put the buttons in a different folder -- sorry, in a different file. So let's just call it button.js. We're going to take our button stylings.
Jason: Okay. Just pulling those straight out and dropping them in here, which means I also need --
Shaundai: And notice how Jason kept styled import in both files because we're going to be -- we're using that style for the inputs as well.
Jason: Yeah, like we're using it here. We're using it for the input. So we have to have it available.
Shaundai: Yep. Then we're going to take the buttons themselves. So what we'll need to do is declare a new name for a component. All of those buttons are inside of our app component. Now let's do export const capital B button.
Jason: Okay. And do we want to export both of them? Like we could just do one of these and one of these.
Shaundai: Oh, yeah. I didn't see what you were doing. Yeah, so this is one way. Let me take a step back. What Jason is doing right now is just exporting the colors for the buttons that we did. This is completely valid. You can do that and then export button and blue button and import them into app.js and it'll still work. This is still like a separate style sheet, though, because we don't have actual buttons or functionality. So what I was thinking -- we were on two different paths, both totally valid -- is to add in the buttons, the functionality for the buttons, and then have this be its own separate component. So what this component is going to be is its own little package of the button, the functionality, the styles. And we're going to just pass down state to our children. So we're exporting const button, and you're importing your prop. Then we're going to -- yeah, beautiful.
Jason: Yeah, just renaming so I don't have the collision with this one.
Shaundai: Okay, awesome. Then from app.js, we'll take the buttons and the props that were in there.
Jason: Okay. So would you -- would we kind of take this out and make it something you would control with like, you know, a background color of some sort? How would you do this if you were -- because we probably wouldn't export two buttons from this file, which I'm realizing we're currently not returning anyways.
Shaundai: Yeah, we're really just -- we just kind of did that for style's sake. We don't really need the blue button. Another way that you could do it to make it cleaner is to have one file that's dedicated to the basic button. So like one default button file that would be the styling for default button. Then a functionality for default button. Then you'd have a separate file for blue button. Or it may not even be a blue button. It might be a style you declare at the top of the another file that's only lines 10 to 12. It just adds the extra styling to it.
Jason: And like we could -- we don't have to use just one of these, right? If we use default button to make button and then I were to wrap like this button, does that -- like would that work? Can I --
Shaundai: Yes, it would. I just want to see how it plays out. But yes, it's not going to have any styling on it or anything.
Jason: Let's see what happens. I'm just going to export this and let's see what happens when I do it. So we have our default button. I'm going to -- we need to actually change this over to be a default button. Okay. So now theoretically speaking, if I swap out -- so if I import my default button and blue button from button, then I -- oh, wait. I need to actually get button, not default button. So I get button. I get blue button. Then down here we're still using button and blue button. Assuming -- let's just see what happens. Let's try it. So I'm saving. So it kept the default styles. It didn't apply the override.
Shaundai: Yeah, so let's go --
Jason: But it does work.
Shaundai: Love it. Yeah, and I think if we go back -- yeah, so like I said, it's not adding in any additional -- wait, so we're not using blue button anymore.
Jason: We exported it so the one at the bottom here is blue button. But I think what you were saying is if you were going to do this, you would just put this at the top. But how would that apply to the background color of the button?
Shaundai: So what I was going to do is instead of having these buttons here at all, instead of having -- sorry, you would have them here, but build out the entire button in the button.js file.
Jason: Oh, I got you. Okay. So we can -- let's get rid of one of these. When we're dealing with the -- just get rid of that one, too. Let's look at actually building out the button. So let me get rid of this blue button we're not using. And now we're in here. So we're building out the whole button. You're saying even the text and stuff you're wanting to pull out.
Shaundai: The text, all that stuff could stay in here. You can add it as a prop. I'm not going to overcomplicate it, but yeah. For the sake of this, let's just keep everything here button-wise. Then we will use this as our single source of truth. So this button is going to be a child of app.js. So we'll still need it. Like this button will still work and all that stuff, but it may not be called button.
Jason: Yeah, so this is much simpler here. We've kind of simplified this down to where we know we need a button. We know we need to pass in the input value.
Shaundai: Yeah, but our styles aren't working yet. And the reason why is because we just have -- like this button doesn't actually have any style. So if we exported default button --
Jason: Well, this one is working. So we are getting our -- like our styles are working.
Shaundai: Oh, perfect. Yeah.
Jason: It was the override. I think to override, we'd have to grab something from the props and make sure it ended up down on this one, which I feel like I've seen -- there's something in the styled components docs about composing that. But we don't have to do that today.
Shaundai: Okay, cool, yeah. So you've got your nice little neat styles. Again, if you have a big app and you want to use this everywhere, you can use it in multiple places. Then I don't know if we have time to go through -- there are different ways you can add different stylings to it. Or here, let's go through this example. Let's say we want to -- we have a scenario where we have different types of buttons at the company. We have our sea green button, which is our default, but we may have a disabled button color that's common across the company. If you're going to delete everything inside of your app, this is what the color is. So what we'll do is we'll change the background color based on whatever this prop is. So let's make a new disabled -- we're going to make an object that holds all of the colors -- sorry, it shouldn't be disabled. This should be background color or something. We're going to change const background color, and we'll make it an object that has -- let's say default is sea green. So default comma sea green. Let's make a disabled color, which would be gray. And let's make a destructive color, which would be red. And this is a common situation, right. So now what we can do is pass in these colors as different options for our colors. And there's ways that you can get really complicated with this. Or not super. You can say like different variants and all you would have to do is when somebody uses a button from your component library, all they would have to do is say this button is default, and it would do the background colors, the font, the size, the hover colors, and whatever else based on what you have set as your default. So this is just a small example of where you would get started with something like this.
Shaundai: So we'll have background color be one of the props that we can pull from for this.
Jason: And should we line it up with what its function is? So I can say by default, it's a default button. But then I can pass in it's a destructive type or a disabled type. That way we're not describing the style, we're describing the function, and the style can support that function. Cool. So I guess I would do the same thing here. Type equals type. Then I guess we can move this thing above our styled component because we're going to use it in there.
Jason: And I like to declare things before I use them. So then this changes a little bit. We can do something like instead of --
Shaundai: Yeah, one option might be instead of -- and this is just like the low-hanging fruit. Instead of says props.input value sea green and black, you could say backgroundcolor. -- whatever the prop is. So it's looking for -- the props is going to be looking for the term default. So we could say if it's default, we want the default color. So it would be background --
Jason: So we can do like background color around props.type? Is that what you meant? Or am I still doing a check for like the input value?
Shaundai: No, this is fine. This is fine. Let's keep going this way.
Jason: Actually, if I take this and go back to where we were, then if we don't have a value, we can go to backgroundcolor.disabled, but here we can do the props type. Then theoretically speaking -- so it's disabled now. It comes in. We get sea green. But then if I come out here and I mark it as like type destructive, then when I start typing, it goes red.
Jason: Look at that. Look how slick that is. So we were able to quickly say, you know, this is -- and now I know what it is. I know this is a destructive button, instead of having to look at the styles to intuit that a red background probably means destructive. I like this. I like the descriptiveness of it.
Shaundai: Right. So now we're just adding a level of dynamic capabilities to your CSS. So as we're building this component library, nobody has to remember all of the different props that you put on a button or copy and paste all of the stylings and things like that, that you put on the original put don that you built for the rest of the company. All they have to do is say, okay, this button in this place should be a destructive button, so it's going to be red. And it already comes with the different props and functions that make it work. They just have to declare what kind of button it is.
Jason: And we can take this a step further, like keeping on your mama component. So you can have like further nested children. So we can just make whatever is in here show up as the button text. Then that means that out here, we can take our button and say, like, delete me. Now it will respond to us. But then if we wanted to take this out and this one is not destructive and maybe this one has -- we just want it to always be -- that one always is on. Then we can say, like, add -- now we have buttons that look like what they're supposed to do. We can kind of see that happening, right. I love this. This is really, really cool.
Shaundai: Exactly. Yeah.
Jason: What is up? Thank you for the raid. Welcome, everybody. We're just coming down to the end. Stay tuned, though. Here in about ten minutes, we're going raid somebody else. We've been making React components today. What is up, y'all? That's a good -- I like that raid emote. That's a good one. But yeah, welcome. Thank you for hanging out. So Shaundai, what else should we look at? Are there other resources that people should dig into? Like if they want to go further with this, is there somewhere you would recommend for kind of getting stuck in? Anywhere else in the last few minutes we've got?
Jason: Yeah, and you know, you bring up a good point, which is when you're writing code, it's not just instructions to the computer. It's instructions to future maintainers. Code is a communication platform. And if the code that you write is easy for somebody to read and to understand, then you've done a good job of communicating to them that, that is how you should dive in. I know where to start. I know what to edit. I know what this thing does. I'm significantly better set up to succeed than if I'm doing this off of guesses and what I can figure out by breaking it and seeing what changes on the screen, right? (Laughter)
Shaundai: Yeah, and there's so many stories. Myself, every day I'll go back to code and be like, oh, my god, who wrote this? And it was me. Every developer needs to write code that your future self will love. So really practice getting clean code or figuring out what syntax works best for you, best for your eyes, and what you like to see. Maybe it is that function keyword or maybe you like the const like I do. But figure out what that is and then stick with it, keep practicing. Separate things out as much as possible. But yeah, strong, strong advocate for all that.
Jason: Yeah, absolutely. I mean, it just makes such a big difference. So I guess from here, where should somebody go if they want to learn more about you?
Shaundai: About me? I'm always on Twitter. So you can find me. One of the perks of having a unique name is my first name is a handle for everything. So if you look -- and I'm one of the only Shaundais out there. So if you ever Google Shaundai Person, you'll find me. But @shaundai for Twitter, @shaundai for GitHub. I'm an Egghead instructor as well, working on my first course. Do you want to have input on what my first course is? I have until midnight tonight.
Jason: What do you think, chat? What do you want to learn? Here's what you're going to do. Follow Shaundai on Twitter and tweet at her what you want to learn. I want to learn how the React Component family gets along. Like, I want to learn -- I want more of this visual metaphor because it's so, so good.
Shaundai: Yeah, I will button that up. Your options are either TypeScript or React. Or Styled Components. So let me know what you want to learn more about. If it is the React family, I love that too. That's a really good idea. It may be the React family.
Jason: I think it's Great. We have votes for it in the chat. State, yep. Something with metaphors. Agreed. I think it should definitely have lots of metaphors. No, I can't wait to see what you create. I've had a whole lot of fun learning from you today. I think this is going to be -- it's going to be a great course. Make sure to shout about it so we can all go and watch. And with that, chat, I think we are in great shape to start wrapping this one up. So make sure you remember, we've had live captioning this whole show on the learnwithjason.dev homepage. That's made possible by Rachel from White Coat Captioning. Thank you so much for hanging out with us. Captioning is made possible through the generous support of our sponsors, Netlify, Fauna, Auth0, and Hasura all kicking in. Any parting words before we send everybody off to the rest of their collective Thursdays?
Shaundai: Happy Earth Day, everybody.
Jason: Happy Earth Day. I love it. I love it. Shaundai, you are a joy. Thank you so much for hanging out. This was such a pleasure. I hope to see you again. Chat, stay tuned. We're going to go find somebody to raid. We'll see you next time.
Shaundai: Bye, guys.