Lecture Script

Summary

Action Items

Class Logistics

Tailwind CSS Introduction

Overview and Philosophy

Key Features

Setup Requirements

Important Limitations

React Controlled Components

Demonstration: Color and Text Controller

Built a demo application with two components to illustrate controlled component concepts

Box Component (Stateless)

Input Area Component (Controlled)

Key Concepts Demonstrated

React State Management (useState)

Fundamental Concepts

State vs Props

Component Re-rendering Cycle

UseEffect Hook

Purpose and Usage

Dependency Array Behavior (important for quiz)

  1. With reactive values: Effect runs on initial render and whenever any listed value changes
  2. Empty array []: Effect runs only once on component mount
  3. No array (omitted): Effect runs on every component re-render

Cleanup Functions

Notes

Transcript

Hello, this is week six class. February 18th. It started a little late. A couple issues. Traffic issue. Delay a little bit, and then some technical issues. Getting started a little late.

We were gonna start building, putting an app together. I decided to switch a few things around. Because I was thinking about it and I want to pull I want to switch some things around throughout the semester. We're going to do a little bit more of the introductory stuff in the next couple weeks and then come back to some of these same topics and talk about the more advanced things because I want to be able to get The introductory topics of all these things I'll do earlier so that I can start working on things that are usable.

Oh. So we're going to look at those and then the other That's going to use React state. We'll talk a little more about state. Depending on how things go with our second demo and where we fall, The other react hook we might talk about today is the use effect hook. And the use effect hook is a hook that's used in React to interact with outside systems. So when you're building a React app, Everything that's in your app, you should have direct access to.

Tailwind is another CSS framework that has been many over the years. As I mentioned, Bootstrap was another very popular one for a long time. But the fundamental difference is Tailwind is looked at as a utility first framework.

So if we put this card body class on something, that's going to apply a bunch of different rules to make this look like what they're styling like a card body. So let me come back to looking at Tailwind. And Tailwind is a utility-first CSS framework. Created by this AdamWait a second. Um. Launched in 2017. It... I'm trying to remember the details of the article I read that he wrote. But basically he was building this small little framework for his own little blog.

And people were seeing what he was doing and they were like, "Oh, that's a really interesting approach to doing this." You should release that. So then it got expanded out and released into a full product. And now we're at the 4.0 version of Tailwind. And the idea that he had for this with this utility first approach. Is instead of putting a class on an element that's going to apply a bunch of rules to make an element look like something, His idea is every class that we put on an element is going to be One CSS rule.

And you're going to build up a bunch of classes to build up the rules you want. Each of theseTable one classes. Basically map over to a CSS rule. So, for example, if you want to put display flex on an element, You put the flex clasp on. And then if you want a flex column, you do flex dash column. That'll be a flex direction column. And when you start seeing it at first, You start seeing a lot of classes in your HTL.

But where it becomes efficient is These single purpose classes that are defined as a single rule, Only get included in your site if you use them. So while the Full Tailwind Library has Rules for every single CSS thing you can imagine. When you go to build your site, The tailwind Tyler plug in or whatever you're using depending on What environment you're in. scans through all your source code It looks for these known specific tailwind classes.

and when it finds him it creates this big giant list and it says okay he used She used all these classes. We have to include them in the CSS code. So then it bundles all that together and builds a style sheet that uses those classes. Those classes are very simple and they may be reused throughout your site. So this flex class is only in the stylesheet one time. So now, if you were writing CSS the traditional way, and you were putting display flex onLike a lot of elements?

It also allows for very fast iteration and even prototyping.

Because right when you're building and you're in the HTML, you see all the CSS that's being applied. You don't have to go look for a style sheet and be like, OK, what class is this applying? Is something inheriting from it? Is something overriding it? If I want to change something, go find it, change it. Or what a lot of people end up doing is just go in and write in an override CSS. So you start to build up a lot of-extra CSS that's just getting overridden which bloats the build.

It's really like when we see it the first few times, We'll probably, and I'll be doing this too, we'll be looking up a lot of the tailwind classes because, you know, we're not familiar with or we'll forget, you know, which one. Which order is this word in the class? You might think, okay, is this really fast? But once you start actually building with it and you do some Couple projects or a bigger project.

It's all done in rev units, but 12 pixels, 14, 16, 18, 20, 24, 30, 36, 48. So if you want something between those, You don't really have a value for that. So that's where these arbitrary variants come in where you can say, and I'll show you what that syntax looks like, you can say text dash square brackets and put 20 pixels in there or whatever you want. And it'll create those variants on the fly. There's also the ability that if it's something you're gonna use a lot, In your tailwind configuration, you can define new-values for jail.

Safe. I want this to be available everywhere. And typically with like background colors and stuff, you can do that. Oh.

Arbitrary variants and arbitrary properties can be constructed on the fly. So we use square brackets for that.

So like M, we're going to find out M is the class for margin. So it's m dash of value. Now Tailwind uses rem units by default and it uses quarter rem units as the value. So REM, one REM is 16 by... Most browsers must Settings have been changed. 16 pixels. So quarter rem is going to be 4 pixels, right?

So by default, whole units are four pixel increments.

And then they do have decimal values in between. Not every rule exists, so some of them you have to do these arbitrary things. So we'll see M is for margin, and then there's like an MT dash, an MR dash, an MB dash, right, for all the different margins. We'll put values in. If you wanted to create something that doesn't already exist, you just use a square bracket notation and whatever you put inside there will be used as a like a literal value.

Because all it's really doing is looking for that string data. So It's really simple. The downside is you have to be careful about how you dynamically creating Because it's looking for a specific class, like in this example here we have M dash brackets 5P.

You can't really create this dynamically.

And what I mean by dynamically is I connect, concatenate strings together in code on the fly because Tailwind's not going to see it as a complete string.

The biggest difference Just make sure you know you're in the dots for the version you're on. The biggest difference was how you extend it. So when I was talking earlier about making your ownVariables that are gonna devalues your commute within the classes. You do them differently in four than you do in three, so you have to just know which route So what are some reasons for choosing Tailwind?

We have a little different spacing on that one. Responsive modifier, so we have all the built-in modifiers. So if we look, let's see where we're going. So if you look at this, it's got a built-in grid. Again, if you don't like those The breakpoints of the grid, you can change it, but they're small is less than They're small, break point is 640, the median is 768, 1024, 1280, and 1536.

And basically you just Use that prefix syntax with the colon and when you say MD colon shrink zero that means at the MD breakpoint or 768 and above it will apply shrink zero. And that's how you do your responsiveness.

Typically do a mobile first design because that's how their framework is designed.

I think that one large website we worked on Um... I think the final CSS for the site was somewhere between 10 and 15 kilobytes.

versus what typically could be 100 or more kilobytes. So it considerably got smaller.

Some of the other things that you have to keep aware of though is To use Tailwind, you have to use some kind of build system.

So we need some kind of system that's going to process our code and figure out what we actually used and strip it down to just that. So that's why we need a note system. It has plug-ins for Tailwind that make this really easy.

Yeah, so they have this play CDN.

bring tailwind into your site and kind of use it in like a Followed and typed. And you notice that this is a JavaScript script, not a CSS file. And that's because this JavaScript script will process your HTML page and figure out all the styles that are there and build a build for you right out of the fly. So it's not really meant for a production site, but it's really good for small pages that you're just playing with or trying to figure things out.

Then you can start using the Tailwind classes right away without a building plan.

Guides for all the major frameworks, how to incorporate them, if you want to use the Tailwind CLI. So the Tailwind CLI is one way to compile Tailwind. So, where I said you need a build environment, well, You can use the build environment, or you can just configure the tailwind CLI so when you run the-on the CLI, it knows what files to go look at and processes them and builds a CSS file for them so that you can do that.

PostCSS is a really popular CSS processing utility.

Found these? Oh. It's basically a way to Bring modern CSS into your project and there's all kinds of plugins for it. The tail end has a post CSS plug-in, so if you have a project that's using post CSS, You can incorporate it that way and then they also have simple instructions for using VEEP because so many people are doing it with VEEP.

So we could look here real quick at what this looks like in V. So if I just create a folder here real quick, we'll just call it Create a terminal and we're going to create a VEET project. So we use the same like we would for Vite, right?

I'll probably be looking at all of them as we go, just so that you can all see. We'll look at the docs, find it, and we decide. So when I said dynamically generated, hopefully that made sense. It just means the The strings in their entirety need to exist somewhere in your source code. If you are doing something that's building dynamic, for class names, then you probably want to also just have a text file or something that's included in your templates that says something like, included style or something, not TXT, and put the strings in there too that you want to make sure exist.

Or you can do things like ternaries.

So instead of building the tail and class name out of pieces and concatenating them together, you can do something where you have multiple different, like,Great. multiple different versions and use like a turner or an if-else statement to be able to apply them, then that'll work because it sees the whole class name inside your source code. Like I said, we'll come back to us. Just a little bit.

Definitely a deprecated concept from Two or three versions ago. The other thing is when we're talking about state, we're gonna have a slide here that's gonna explain state more, but your goal should be So try to make as many components that are what they call stateless. So... As we go through this example, I'll speak to that.

There's going to be one of the components will be stateless and one will have state. Um. If you don't need state in a component, you shouldn't add it. But if you do need state, obviously you use it because you need it. Okay, so keep as many components stateless as possible. Use functional components. you The new state hook You can only use it in a functional component and it has to be at the top level of the component.

The call to the U-State hook, which was sitting in These slides here has to happen at the top most level of the function. You can't like, use it. invested inside a gift statement.

UseState basically gives a React component the ability to remember stuff.

So, in between these re-renders, if you need your component to keep track of something, that's what states will.

If you just need your component to show information, That's what the props are for, right? You pass the information to the component and it can show it and when that information changes it will update what it's showing. But it doesn't really need to keep track of that because it's being given that information. Okay, so. Think of it as like a memory for that component. Specifically for you.

We import the useState function from the React's library. And then... We call useState with an initial value, and that's the value that it puts into state. Simple or complex objects. And the useState function returns an array. that has two Values.

The first value is a variable that references what is the current value in state.

And the second variable is a variable that is actually a function. that can be used to change the value that's in the state. So typically you name them whatever you want the value to be called and then you typically name it a set that value type name. But again, naming is completely up to you. Okay.

So we call setCount for example in that last one. And then that function updates the value that React is keeping in memory in that state. then The component looks and says, where was that value used? And it'll even look at, oh, you've used another component that this is passed to via props. And it can go down and nest it down the chain. But as long as that value is passed around, it looks at it and says, here are all the places that value needs to update.

And then the React framework will look at all those components and re-regra. wherever it needs to get the updated data and your UI just looks like the data updates. At no point in time are you manually querying or updating anything in the network. So again, some other, we already said this, but only use stake is put at the top level component, so it's directly inside the function. Like not nested in anything?

Never loops or conditionals. Updates to state are asynchronous. So they happen very quickly, but They do not happen necessarily synchronous in your code. So if you had a big block of code that's running and calling some state updates, it might not happen. Following code could execute before they finish updating state. And when you call the set... The center of whatever state value you have. That's what you're explicitly telling React to read.

Let's start withTalk about what are we gonna build. So I'm gonna build a, A little widget.

That's going to have an input area. and it's gonna have a box underneath the equator.

The box is going to have text that goes inside of it and it's also going to be able to change colors. So we're going to have two different pieces with that.

So this is a perfect example of when we use props in a state.

So we could say, okay, We want the box to be able to be given text to show.

So we're going to add a prop on here called text.

So this is like the first thing of how we see, okay, when we get props passed in, we can create things that are reusable. So like, In the other demo, which you may not be familiar with, Um...

Whatever text we put in, if we-I think this browser, I have the React Developer Tools installed. Let's see. I do. So if you install the React Developer Tools extension, React Developer Tools. You'll get a components tab, which the components tab will let you see.

Yes, you could always... and it will do the same thing. But let's say you want to do inline styling for something. So the way you do it in React is you create an object. of the CSS properties written in JavaScript syntax, not CSS syntax. So that means camel case instead of hyphens.

And you create an object and you put that object on the style prop. So we can create a const.

And then inside this object, we put what CSS properties we want in object syntax.

All right. We have some basics there. Now, We want to have Some inputs.

We want to have an input for changing this text, and we want to have an input for changing the color.

So now, this component we build here is not a controlled component.

It is a simple, stateless functional component. It does not use state, but it uses props. Obviously the text and the color are going to dynamically update and refresh the component, but it's not keeping state of itself.

Okay, so for the controlled component, We're going to do this A little bit... Kind of... I want to demonstrate something else with this too. So normally with a controlled component, we probably would put state right in this component. We'd probably say, What is the value of this particular Text input, what is the value of this color? And that would be fine. But I actually want to use the values of these elements inside the box component.

So I can kind of rethink how I want to Architectus? So it's easier for me to use those. So I start to look at what is a shared parent component. And a shared parent component is app.

because app has both of those inside it and I can use props directly on it. I'm going to put my state in the app component in this case. So in the app, I'm going to create a state value for both the text and the color of the input and what's shown in the box.

I'm trying to type. And why can't we change it? It's because this default value state is getting passed to the input value as the text prop. That input value of the text prop is being put directly into the value prop or attribute of the input element. Same thing with the color slide. We technically can choose other ones, but it doesn't actually change them.

When I'm over here trying to type, You think, like, how come I can't, like, if I can't type here, how is it going to know to update? And it's because it's going to grab every keystroke I do as a change.

Before It re-renders. So we're going to be able to capture that change and then save it in state.

And then that will then reflect via the prop of what's shown. So now if we say, OK, on the input, I'm going to name these a little differently than co-pilots trying to help. I'm going to say handle. Handle, text, change.

So what we can do is we can say, On change, so anytime this input has a change, what do I want it to do? Well, I want it to run a function.

Now, Just like we've had Just like any event handler, what gets passed to a Changement is the event itself. So we can capture that event there by capturing E. And we're giving it an arrow function because we want it to run this function when a change happens. So what is the function that runs?

to change the state that's up here in the app. Remember I said in like the first time we talked about React that it's always a unidirectional data flow and the data always gets passed from parent to child? That is true, and you see it with the props. But if you need to change a value that the state is held in a parent component, then you need to pass a function down as a prop to the child that the child can call.

And then the child can call that function and update the data that's in a different spot. So that's what we're doing. So now, if we come back over here, we should be able to change this and have the text updated real quick. Now, I know that looks a little like You know, like, okay, we're wiring all this together. But you can see that we do not have a DOM element or a, we didn't add our own, like, we did add, we added a change listener, right, using this on change.

Now maybe I wouldn't in these cases because the selected input that I'm using here are basically their native HTML elements and I'm not adding any value by having them as a separate component. But let's say I had some more complex logic that I wanted to put in or something. I might extract those out into their own. Hopefully that kind of makes a little sense with how this would work. With Passing these functions down as props so you can change state from a different component, that's another thing that we're going to have to probably be seeing a lot.

And, uh... We'll probably spend the whole class next week building a couple different examples ofA React app, and I'll probably just plan ahead to show all the different hooks in the same day. So this will probably be a pretty demo-heavy class next class. Um.

I also will Probably be using two or three other hooks next week that I won't have slides tonight for, but I'll have slides next week that we can talk about those.

So let's just quickly go through this and then I will refresh us when we actually use this user practice week. A little bit about it, but let's just go through it. Talk a little bit about it, 'cause there will be a quiz, you'll see on the assignment on board, another quiz coming, so the, Could be questions from anywhere in these slides, so let's talk about through these for five minutes. So we talked about use state as a hook.

What it is, is it's a The hook that lets your components Tap into the component life cycle. to be able to say, oh, this component is re-rendering.

Do I need to go fetch some data from an external source? Do I need to do something? It's mainly used for synchronizing communications with external systems, whatever those might be. You'll see that the useEffect hook, instead of getting an initial value, it gets a function pass to it.

So I'll show you a code example of that in just a second. But basically, the useEffect hook takes two parameters, we can call it.

It takes first the function that you want to run and that has all your logic in it for doing whatever you need to do.

And the second one is an array. of the dependencies that this effect should run for.

So this is kind of a It's not really an external system, but you can look at the document, the web page document object as like an external item, so that's why I'm using this here. We have state still, and then we call useEffect, useEffect hook, and we give it this function, and we say any time the count variable changes, I want you to run this code. So basically what this is doing is This component is using its state to change the number on the button every time the button is clicked and also changing this value in this paragraph every time the button is clicked.

But it's also every time the button gets clicked and changes that count variable, It tells the user factor of this function and this function says, okay, I gotta update the documents title. So the document's title is not necessarily something you would have access to as part of your React app. because it's part of the metadata of the head section. So this is a case where you would have to somehow interface with this other object.

This is also commonly used to fetch data. So if you have an Ajax call that needs to go out, one example of that would be, let's say you have a select list that is telling it to Let's say you have a list of things, and the list is always going to show you 20 results. And you give the user the ability to say, do I want the highest scores first or the lowest scores first?

And these things are coming from an API. That's the scenario. You would probably have that value of are we sorting from highest to lowest or lowest to highest in state somewhere. And it'd be a control component when the user selects a different value of the select list, it would update the state. That value in state would be passed as a dependency to a useEffect code. And inside that useEffect hook, it would then say, OK, that has changed.

I need to do a fetch call to go get new data from the API. displayed on the page, whether that's updating a different variable state or doing something different with it, but the actual Ajax call would happen inside the user. That would kind of be an example of that. I'll show in the demo next week fetching data from an API endpoint with useEffect. So we'll definitely do that example. You see here like this use effect hook has a Array, I said it's always an array.

So if you provide actual reactive variables as the dependency array, What happens is, In the React component first renders on the page. It will run that ease effectively. And it'll do whatever. So if you need to fetch some data to get some additional data for something, it will do that. And then it will run that effect hook any time any value in that array changes. So those are the two ways that that would work.

If you pass an empty dependency array, so still pass an array but it's empty, The useEffect function will only run once.

and it'll run right when the component makes its initial mounting on the down. So when it first gets created. So, if you need to fetch data from an API You fill some data on it, but you're never going to fetch the data again to update anything? then passing an empty array is a good option because it will cause the array or the effect of the two. Do that data fetch once.

And if you leave the array off completely, So it's just no parameter passed here. Then that use effect will run every single time the component re-renders or refreshes.

Regardless of whether any data that's important to it changes or not, So...

You gotta be careful with that because Typically those use effect hooks are doing something that you don't want to run on every single type of mutation of this disease. So typically you're going to want to use the first two, but there are some small cases where You might want whatever the use effect to just run every single time.

So, this is the last one. So the use effect hook can also return a cleanup function.

So this is useful when you're doing things that might need to be disconnected or stopped. So maybe you're connecting to a system with like a web socket and you're opening a connection that's staying connected. Or you're setting up an interval that's going to run every 3,000 milliseconds. And you want a way to stop those. So You could return a cleanup function. And that cleanup functionUm. can have whatever logic in it it needs to undo whatever the use effect is doing and then Every time the component re-renders, The cleanup function is run and it's given the old value of state and props.

This is showing the fetching data. So this is kind of like similar to what we do All right. We already talked about build and dev systems earlier. These slides are in here just for-Just have them in there. And then if you haven't read these four pages about these array functions, So I want you all to read these. I even posed some questions for the quiz about these different array functions. The reason I called these out is they're all very useful for React specifically.

But the first three should be JavaScript functions that you're very familiar with anyway.

Three, I will put up these slides.

I'll put that demo up. We'll just plan on next week, I'll Just plan on doing the demo stuff I was going to do tonight, but like... Do all the pieces of it, like swoosh. Thank you.


Introduction Tailwind



Tailwind CSS 핵심 개념


<div class="rounded shadow p-6 bg-white"></div>

각 class 의미

| --- | --- |


Traditional CSS vs Tailwind 방식


Traditional CSS 방식