Lecture Script

Summary

Action Items

Overview

This session focused on building a to-do list application from scratch using React, TypeScript, and Tailwind CSS. The demo served as the foundation for exploring React hooks and component patterns, with plans to extend it in future sessions with local storage, Context API, and server components.

Project Setup

React Hooks Covered

useState Hook

useEffect Hook

useRef Hook

Component Architecture

App Component

TodoList Component

TodoItem Component

AddTodo Component

State Management Patterns

Prop Drilling

State Updates

Data Integration

API Fetching

TypeScript Integration

UI/UX Enhancements

Loading State

Tailwind CSS Styling

Notes

Transcript

You've already been co-pilot for a while. I don't understand what it's doing if they ask you. More specifically, how do we factor something in? Don't use that. Oh, yes. . So the first step is just a very simple It's the base of the demos that we're going to do moving forward. It's just going to store the to-do list and state. So that just means it's basically a memory. So every time you restart the app or refresh the page, it goes away.

Fuck. Oh, that's... The real solution for an app is more of a one time thing. We still use Spade a lot for that kind of thing to give the app a little bit more You're in too. Manage something in state and then the background can save it. Thank you. Just so that the immediate interactions feel more like a grip. So I'll start there. When we get all the way through this, at the very end, we're going to also take inConnect to the API.

into an app that uses the browser's local solution. So that the The data is persistent between browser sessions. Still stored locally in the browser, but it's going to be persistent. And then as part of that, we're gonna actually build the local storage. System for Trash And we're done building there. I'm going to show you framework that's out there that basically does that and provides a hook that we can add to React.

Which is what gives our components memory. Anytime we update space It triggers our components to re-render. And we're gonna pre record.

Typically what the use effect is used for is to Connect with some system that's outside of your React app because your React app itself But Like... Your components.

Need to sometimes talk to APIs.

That function can either return nothing, or it can just be a function that does something like a fetch call. Or it can return a clean up function. We talked a little bit about that last week. If it returns a clean up function, It will run that function first before it re-renders every time.

You can be given three values. Three different types of guns. The first one is We provide a dependency array and you provide values. So basically like you see here. If you do that, then what's going to happen is the first time that component gets rendered to run the user factor.

Let's go run. And then from then on out, any time any of the values that are in that array change, it will run again. So that's one option.

Second option is sending in an empty array. So it's just an array with no values in it. And what that does is it tells the rent. Rather use the effect when you first mouth.

The third option is setting nothing. So that's literally no parameter in the second, for that second. If you do that,Ten. Thank you. runs every time a component rewrites. Weather tonight. First render, second render, third render, doesn't matter. And because you didn't give it anything like a dependency, it has no idea to know, oh, only run the Miesk exchange, so it runs all the time. So most of the time that's not what you want.

So we kind of talked aboutA clean up function, so inside your useEffect function that you passed through, your callback function, if you return a function, That function will run First, before... It reruns the effect.

It's a way to create a Component variable that holds a reference that will stay persistent across rivers So it's not only just a normal variable that could just get reset every render, it actually stays persistent between renders if you perform it.

But because it's not state, It doesn't have any bearing on triggering the re-whip. So you can put a barrel of value in it, you can change the value, and changing the value doesn't trigger the motor to move.

And the other way it's used, and it's often used in a lot of examples, and it's the way we're going to use it tonight, is There's times where Thank you. You have to do something that react can't do. And it's usually related to something that was done. So, the example we're going to do tonight is Something about focus. So triggering focus on the movement.

React itself You can't trigger focus on it. So what You can use ref, use and use ref for is you can hold a reference to a DOM node Inside is rough. No.

You're setting it null initially?

And that creates the rough object.

Okay, so the firstJust a little bigger. So first thing we're going to do is create the meat project. We've done this a few times, but it's npm create meat. At latest, Now, we could, we can pass. Some parameters to this. So that we don't have to answer all the questions. I'm going to go ahead and do that here just so you can see what that looks like. But just know if we wanted to, we could just do it here and it's going to ask us all the questions.

So we can say npm create vm latest and then the first parameter we can pass is the name of the project.

website and we go to the getting started in the documentation they have a tab specifically for me because they have a plugin built for me and they give us all the instructions on what to do here which is But the first oneWhat we have to do is we have to install some dependencies. So we're going to install Tailwind and the Tailwind CSS2 plugin. They showed here being installedHello. AsRegular dependency?

And then... It's got all these dev dependencies that we need during development time. So Tailwind we can actually put in either because it is technically a depth dependency. Just follow the Instructional panel in here. Grab that. We will install both those. Now if we come back here and look, now we're going to see we have tailwind CSS 4.2.1 in our dependent system.

We should be done in the terminal for right now. Uh... But you know what, before I start the dev server back up, we'll finish the talent configuration, because that's the only parts that are going to be So in our config file, Now we want to tell this Okay, we want to use That tailwind plug-in that we just got on? So we're going to import Hello.

Slash. Which is also And then, just go down to this. The other piece we need to do is we need to tell it after the React plugin. We want to add the tailwind plug-in to the plug-ins around here. It's okay.

Tailwind CSX Okay, and I should have done this up to see. Thanks. This line right here.

So an API to pull in some, like, seed data, preliminary mock data. So I'm just going to use this JSON placeholder endpoint.

It's an endpoint that you can hit with fetch that has Basically a database of posts, comments, albums, photos, to-dos, and newsreels. and it responds in a restful way to all the different inputs for that. So...

I'm going to come up here and inside the source directory I'm just going to create a new file called types. TS. And we're really, for this demo, we're only going to put one thing. That's the to-do type. So we're going to take and we're going to export. An interface. Interface, and it's going to be called a to-do. And then we need to define what does that look like. So we already kind of see it here on the side.

Let's just go through it again. We have user ID. Which is in number? Yeah. We have an ID. Which is a number? We have a title, which is a string. And we have completed, which is a deal. So we just created the interface that's going to represent what does a to-do look like. Now we have that. So now the first piece we're going to start with is this F. Really work from the top. Yeah, top there.

So now We are going to need state to manage the list of schools. We want to hold that. So let's go ahead and put the state back in.

So what we're going to do is we're going to say inside of our app, component because we're going to keep the to-do list at the app component level. That's what is going to hold the memory of the act for this particular piece. The app is not going to directly display the TV. Those are going to get displayed in child components. So we're going to end up passing the state now its props so we get to see the parent to child relationship but We at least want to create that state.

So we're going to do-that's exactly what I want. So we're going to put in the new state line. So we're actually using the state code. So... Again, the way we do this is we call the hook while we import it in first. We call the hook. Because we're using TypeScript, you can annotate The types that state's gonna hold, and we're gonna say, well, state is holding an array of to-do objects.

So we can go ahead and type it.

Again, I'm going to use the tailwind classes that I already have used. I'll try to mention what they are as we go through this. Um... I don't know if Get every single one of them. Applied in a way that's going toGradually built this, but We'll start with the H1. So when we use tailwind, and I won't go through this as detailed on all the other components, but for this one I'm going to actually go through the tailwind.

And then we're going to just set that equal to a string. And inside here, we're going to put the tail of the classes. So for the H1, I'm going to use text. 4XL You can see one other nice thing is because I have Tailwind all installed and be configured correctly, And I have the tail end extension and the usual steel cone. I'm getting pre-fills of all these classes. That's helpful.

Let's do EG isRadiant. Dash two, dash VR. So that's gonna make a background gradient. to the bottom right. Let's say from... There's blue, there's 50. Two. Yes, you know. Yes.

We're going to put rounded on here. I will round it large. So rounded large is going to give us a border radius of 8 pixels. Remember, this is the container that's holding these leaves.

We're going to say max-w, so max width is going to be 4xl, which means the maximum size that container can ever be is 880.

In this case, we're going to create a to-do list component And that to-do list component, we're going to make it reusable. that it can show a list of completed to-dos or a list of in-created to-dos. Whether or not Which ever would we cast?

But we're going to build it that way so that we reuse it for both different tests. So I'm going to come up here and I'm going to create a new folder in my source. This is the way I like to organize stuff. We call it components, and we're going to put all the components we build inside that. You can further pick folders, whatever you want. So inside this folder, I'm going to now create a todo list.tsx file.

And we'll have different timings. So that's where we use a prompt. So we're going to say, OK, we want to pass to this to-do list a prompt. That is the title of the to-do list. So... What we'll do is I like doing it this way. So we're going to say interface. To do list prompts. And we're going to say there's a title. Coming in and it's a scrape. And then in the function, We're gonna do that. We're going to say we're going to destructure the props.

So we're also going to say our to-do list is going to take it as a prop. A trot called "To Do's" And it's going to be a to-do array. Now because this is a type of game, Can you get in for it? So we're going to import that from our types file, and we're going to come down here and And That to do's to our destructured promise. The other way we could have done this is we still need to do the types. This makes it easier to do the types this way.

equal to zero So I'm right in the turn area out there here. So a Ternary operator basically says If that is true, the first element after the question mark is going to be used. So I'm going to take a Put some parentheses in there, and then right here I'll put some parentheses, because we're going to output some JSX in here. And then we're going to say, OK, if-The length is zero. I'll put a paragraph that says no toYeah.

But... What do we have? We have an array of things. So we actually have to take that array and turn it into individual elements. So we're going to use the array map function. We don't want to mutate the array, so we can use the map function to do something with the array and then When we do something with the array, We can output a new array comprised of our changes that we just did. So if I take here and I hook it up curly braces it again because again we're inside JSX so even though we were inside JSX moved to JavaScript we moved back into JSX because we're using the-Do you want this in class?

That callback function? Like that? It's going to take an element. It's going to take each element of the array. So that is a single to-do. It's a to-do item in our array. And it's gonna map over each of those And Output or not output, but whatever it returns is going to get put into the new array. So in this case, we're going to take advantage ofUh... Does arrow functions implicit return? and just implicitly return some JSX.

And on this, we're going to do another turn area. So instead of a straight, I'm going to put the curly braces because I'm going to put a ternary operator of JavaScript on there. And what we're going to say here is to do dot completed. Great. Remember we're mapping over each to-do. So we're looking at is the text of this, or is this to-do marked completed?

Okay, so we have that. To do list, set up. Now let's go back to app real quick. And here let's change the East Tailwind classes. Remember I want them side by side, so I'm going to use CSS Grid to do that for this. We could use Flexbox, but we're going to use Grid. We're going to say it's Grid. Then we're going to say MD, so that's doing-The query is for the MD breakpoint. The ND grid dash calls dash two.

And then gap, we have six. So we go to grid gap, we're saying it's two columns if it's over. 7.68, yep, 7.68. And otherwise, it's one column.

I So what we can do here is we can Take and filter are Our state Here, before we even give it to the to-do list, So for this first one, we're going to use use the filter array method because again, we don't want to retake the state object. We want to just create a new array of it.

In here. So I'd like to say to you, So now those are both filtering the to-do state and creating new arrays. And then if we come down here, we can actually swap these out and say, Incomplete into news. completed to do and react's going to know okay we're using this variable as a prop that variable is being driven by The to-dos are evaluated as in state.

Okay, and inside here, function. Two items. Return. I just need something to return. Explore. So bad. Uh...

We only want the button to be there if Uh... So we have this basic structure that we're going to use. What does a to-do item mean? Well, the to-do item needs... Amid crops. So we're going to say, "Ear face." To do item props. And What is going to get passed to it? Well, the most important first thing that's going to get passed to it is one of these to-dos itself, right? One to-do item. So we're going to say to-do.

Shadow, we got a smile. Order. Quarter, dash, grade is... 200. Your room is covered. : ShadowFD, so a darker shadow on hover. And then transitionFD. Shadow, set up a CSS transition on it. Okay. And then on this div, I'm going to add class name. I'm going to add-Flex for flex bars. Sorry for, uh... Align items. Gap of three for a flex gap of... Ready for work, ma'am. Column gap. Flex dash one, the set ofFlex properties.

So now instead of this string, actually instead of this string here, I'm going to use a-The wood strains. Because that's JavaScript, you have to put that inside curly braces, and now inside here I'm gonna say text dashGray, Nash, And then because I'm in JavaScript, Like, a template string, I can use that to do more JavaScript. And now I can say, to do dot completed. I can put another turn area. Not a surprise, you use a lot of toneries in your antics.

All right. Now, This button down here, I want this conditional depending on ifYes. The to-do is completed or not, so I'm going to put Curly braces here and say to do. Got completed. They will use this Operator here. To then say If to-dos got completed, So it's like a-it's a band operator. If that's true, then it will evaluate that second.

So we need to pass A function from the app This component that it can use in order to do that. So what we're going to have Let's just define it and then we can go edit in a minute. So we're going to have a function called onToggleComplete. And on the lead. Okay. We're going to mark them as required. Is that going to be required? Since this is an interface, we're defining what the signature looks like.

It's going to take an ID number, and we're going to go into the state and delete ones by ID number and it's going to return nothing. That's what our function looks like. Now we're going to come down here and we'll go ahead and add them in here because they're going to need to be passed in as props. To the ski moment. We need the props to come down. And then on the input, We're going to say, "Unchange." We're going to say on toggle complete.

So the to-do list is also going to be given those functions because this is that prop drill that I was talking about earlier where we have to pass the same thing because these functions need to exist up where state is. So they're going to exist up there but they need to be passed down to every component in the tree. So it'll obviously not be tonight but next week when we see context we'll see a way around doing this problem.

Thank you. Good. And we'll toggle between. So handle time complete, remember it's a function, it takes in an ID number, it's A call set to dues, that's good. Crucible. Do stop that. Over to do, in case we'll pass the to do, we'll look to do that ID. Okay, so it's checking that ID number.

If that ID number is true, it's going to create The new to-do that basically is taking the existing to-do Expanding all the properties out, but then setting the completed property to the opposite of what it's currently set. And if the ID doesn't match, then it just returns to the screen.

So then down here, So then we need a handle deleted, which I'm just looking here, that looks good. So again, we're taking the set to dos function, we're using the filter to return a new to do and putting it into the to dos state. We're just filtering out one that Remember, if you're a trans-trivial piece, So the IDs don't match.

So we have an add to do component. I'm gonna go ahead and just... Just to save some time, I'm going to go ahead and just build out the component. here all together and not worry about like adding it in pieces. So we're going to build a component that is going to Right here. It's going to be a controlled component. So remember we did controlled components before. We have an input, so we need to code that in state.

That button is going to say add as the text. Okay, the button is going to be tight. equalsSubmit. Hey. And then... We'll add Class name on this. And we'll put the W is full, so that's width full. Small breakpoint WAuto, so auto with a small break point. Dx, Thanks. PG-Blue-500, Texas. This is myRounded, then shall G. Over. For BG. Whoa. 600. Transition colors. Front desk, medium. Okay, so that's good for that.

So this is a control component, right?

So our form needs a submit handler. So we need to do on submit. So when the form gets submitted, what's going to happen?

It also means-Class name flex, flex. Column,Ball. Flex dash row, so it's gonna be a...

Mobile column. Up on mobile row,Gap dash three. Okay, so unsubmitted. When the form is submitted, something has to happen. So we're going to come up here and we're going to just call this handle. Handle cement. And up inside this function we'll defineEight, We're going to define a function called Handles submit. Now, in this case, it's okay because the state's here so we can just do it all all right here but when the form is submitted What, well actually we're not even interfacing with the states really.

So we'll call event prevent default. Then we'll say if the title.trim I don't actually want to return it, but... If the title.trim is Let's do this. So if we trim the title, so trim the text that's in the input element, exists, so that means it's not an empty string. So if we have to take out the white space, then we're gonna do something. So this is how we're gonna only do something if there's actually characters in the title.

And, So we're going to have to call a function called onAdd. That's going to be something that's going to be passed from where the state is for the to-dos down to our components. So we're going to have to call that. Then we're going to call setTitle to set the state of the input field to something empty. We want it to be empty. after it successfully goes. And then we're going to use the Input ref, current, Focus.

The handle I had to do is going to take in the string, and then we're going to end up passing that down to the component as a prop named on ad in the compartment. So now up here we need to make this work. So how is this going to add a new to do? Okay, so it's going to be pretty easy. Hopefully we can get this to, we're going to say const max. X, I need... Okay, so this outline that just added actually just for speed, I'm gonna look at this is what I want.

Okay, so this map loops through. Extracts out the IDs. Then this spread parameter here spreads those out into individual parameters that are passed to the mathmax function and then the mathmax function returns to us the highest one of the numbers. So now we have the max ID that exists. Create a new to do, which is a new to do object. User ID, remember I said we don't care about that, so we're just setting it to 1.

The ID is going to be set to whatever the max is plus 1. The title is going to be set to whatever the title that was passed into this function is. And then completed is going to be set to false to start. And then we're going to call setToDos. And this is another little syntax thing. We're creating a new array to pass the set to do's. Inside the new array, we're using the spread syntax again to spread out the existing todo's array into individual todo elements.

So the last piece of this is we want to make sure we get the data from the API as a starting point. So let's see how the use effect hook works. I'm going to close. So they're full, all these other files. Okay, so now in the app, TSX file. We're going to replace the static data with data from our API. So the way we're going to do thatIs inside of Our app right below ourOkay. Make a call. We're going to take an initialized state with an empty array this time.

So basically we're getting rid of the static list and we're just starting our state with an empty array. And now we're gonna implement a use effect. Fuck. So we just call useEffect. We need to import that from React, so now we have that imported up here. I'm going to go ahead and leave this in here, but I'm just going to count it out. All right, so now inside the use effect,Just for a second. We need to give it a call back.

And then we should give it some kind of, What is it relying on? Well, in this case, we just want it to run one time when the app melts. We just wanted to go out and touch the data and bring it down. So... We'll give it an empty array because it's not dependent on any--Objects. Um... Inside useEffect now, we want to do our fetch call. So we're going to do fetch. We're going to use the Fetch API here.

And we're going to fetch from that JSON placeholder. Did I keep it? I did. So the URL is JSON placeholder type code slash to-dos. But we can add a question mark parameter of underscore limit. Equals 10. And then that will get usJust 10 items. You don't really need... A whole bunch of them. So in here, our fetch call. is the offense from Matt. That URL And then, so remember we use dot then. And inside the first one.

We have to convert it to JSON, so we take our response and use the Response JSON method. Then on that promise, we do a bend again. And inside that then is where we're going to handle our data. So we're going to be given We need to give it another function. We're going to be passing into that function the data. And that data is-It's going to be a to-do array, so we'll go ahead and type it. And then, because we know it's going to be a to-do array, so we want to tell it that's what it is.

And then inside there, what are we going to do when that data comes in? We're just going to call setTodoes. With our data in it? And then there is one other piece where I'm going to add in here. So we'll add that in just a second. And then after this, we really should do a dot catch. In case there's an error in the... The call. And if it was, what we would get would be--Air passed in, we'll do a council dotHere.

The app's going to look empty for a few seconds. So you want to think about things like that. And you can use state and different components to create loading indicators. So What I'm going to set up here is we're going to create another piece of state up here real quick. And we're going to say const Loading. And set loading. So to use state. And we're going to hold the blue in there. Okay. This is just going to be a ruling of whether the app is currently loading or not.

But we're putting it in state because then we can kind of use it in React in a reactive way throughout the app. And then down here in our Our use effect After the late data loads, we can say set loadingIt's false. And then in this error state, We can say, also said. That floating... It's false, right? If we have the error We're going to get the council air, but also if you remember, our to-do list is set up so that the array that gets passed into the to-do list is empty.

The to-do list gives us a message that says there's no to-dos. We already have an error message, like an empty message in our. So we're going to go ahead and set the loading to false. So this is really just handling the API is taking a while to load. You might be able to simulate this in DevTools by setting a 3G connection or something. We'll see. So then what we do to use this Is down here where this component is returning the apps JSX?

We can instead say if Loading. Return a different element. And as soon as the loading changes, the component knows it needs to re-render. So it's going to re-render and it's going to say, oh, loading's not true. So let me pass that and go to the next thing. So it's kind of like conditionally rendering based on the value that's in that state. Let me just see...

Actually, no. There won't be a quiz this week. I'm going to take that off the slide because I forgot we're signing the midterm on Sunday. So there won't be a quiz coming for the students. this week there is one out there that's due this coming weekend so make sure you take that one but I won't assign a new one but do look for the midterm exam coming late Sunday May probably it'sIt would probably be great.

late Sunday night. I'll give you the week to do it. Just have it in before the end of the day Friday at the end of the night. And we'll have that. And then obviously we do have class still next week, but the term is just taking term off. Okay? And like I said, we'll do some more React stuff. Hopefully we can kind of wrap up the basic React stuff next week. And then I can do the one other React. I have another set of, like...


Continue with React



React 핵심 특징



React Hooks


대표 hooks