Transcripts
1. Introduction: Hi, my name is Travis Arnold. I've been a designer, and developer for over 10 years. I was first introduced to React a couple of years ago, and I immediately fell in love with it. I fell in love with React because it maps so well to the design tools that I've been using for so many years. This lesson's great for anyone that's had an interest in React, but might be a bit scared to get into it. We'll start by going over what React is, why we'd want to use it in the first place, and how it can help us in our development. Next, we'll hop into a real-world example, and build a small gallery app to see how React can be used to its full potential. By the end of this class, you have a basic understanding of how React works, how we can pull in third-party libraries, and use some newer JavaScript features. Before taking this class, you should have a basic understanding of HTML, CSS, and JavaScript. Don't worry though, we'll go over everything line by line to ensure you can complete the project on your own. We see React being used more, and more every day. I can't wait to show you the basics, so let's get started. See you in class.
2. What is React?: Welcome to an introduction to React. Thank you for taking this course. What is React? React is a JavaScript library that helps us build interactive user interfaces. It's created by Jordan Walke, a software engineer at Facebook, and it's still supported and maintained by Facebook today. Instead of step-by-step instructions, we describe what our app should look like and React will take care of updating the DOM for us. First, we're going to start with some high-level concepts and then we'll jump right into the code so we can learn how React works. React uses a concept called the virtual DOM. It's a representation of our current UI state. As you can see here, we have two different states. You can imagine if you had a div with two buttons and a span tag, and we wanted to increment or be able to decrement a number. Well, this is what it might look like if maybe we were to say, click on the plus button and want to increment the number. React will see the second state that we need to move to, and it could div the changes efficiently and then move to that next state and update our DOM for us. This also allows us to render to multiple targets like web, mobile, VR, and any other platform. How do we communicate with the virtual DOM? React provides us with a create element function to create these elements to communicate with the virtual DOM. It's basically a description of what we want to see on the screen. We can pass a type which is basically just an HTML tag, or it can be a component which we'll learn about in a little bit. Then we can pass props, which can include things like onClick, onKeyDown and many more events. Finally, we can pass children. This can include text and other CreateElement call or even a function. There are some small nuances like using className instead of class and style needing to be passed as an object instead of a string because we're in a JavaScript environment. If you've ever seen react before, you've probably seen this HTML like syntax. This is called JSX. We use a tool called babel that understands this JSX and compiles it down to something that the browser can understand. Babel is a JavaScript compiler that takes code, transforms it, and returns the JavaScript code and a different format. As we can see here. We're transforming it from an h1 tag that looks like HTML into a function call using create element. If we were to pass some props here like maybe style, color orange, we can see how this is going to be transformed in real time. You can visit babeljs.io to play around with this live example and get a feel for it yourself. We can use any valid JavaScript expression inside of curly braces in JSX. JSX itself is a JavaScript expression, but remember it's just [inaudible] on top of create element. Sometimes if we need to interrupt with JavaScript, we can. We can see here we have a name variable that we declare, and then in our element variable we can actually use that name variable. This would resolve to hello Travis. When mapping over collections though, we do need to remember to provide a key prop to React. Keys help react to identify which items have changed, been added, or removed. Finally, we can talk about components. Components are the basic building block of React. It allows us to split our UI into independent, reusable pieces. We can compose multiple components together to create even more components. We use functions for stateless components and ES2015 classes for stateful components. Stateful components also offer us life cycle hooks that allow us to hook in certain parts of the rendering process. Let's look at how this works. As you can see, we have a stateless and stateful component. Stateless components are very simple. They're just a function that returns a react element. As you can see here, it's the same thing as before. We're just saying hello, name. Which name is declared as a variable above called Travis, so this would result in hello Travis. Things get interesting when we move to a stateful component. We start with an ES2015 class and then we extend from React.Component, which comes from React. By extending from React.Component, we inherit some methods and other properties that we can use and React will understand. In this basic example, we just declare a state property that's going to hold another name property named Travis. Then we'll have a render method which React will call and will return Hello, this.state.name which would be Travis. It's also helpful to note that a render method is required for classes. Both of these components will result in the same thing, but they're written in two different ways. Let's find out how state can help us in our applications. State gives us the ability to make our apps interactive. It can be an object of anything including strings, arrays, and even functions. We can update a component when new state by using the set state method which we inherited when we extended from React.Componet. It's helpful to note that react helps us by adhering to a one-way data flow. You can always think of state coming from the top and trickling down to children components and providing them with that state. As you can see here, we've declared a component using a class called counter. We extend from React component like before, and we're declaring some initial state called count. The count starts off at zero and we want to increment or decrement, the count based on what button we've clicked on. As we talked about before, we have to call the setState method in order to change the state. setState can either take an object with the new state, or it can take a function which receives the current state and then returns its new state. That's what we're doing here. If you can see these increment and decrement functions, they received the state and they either add one to the current state or they subtract one from the current state. If we click on this button a couple of times, we can see that we're actually incrementing the state. Likewise, if we click the minus, we decrement the state and go down. As we saw before with the virtual DOM, every time we either decrement or increment the state, it will div the changes and update the component appropriately. Since we're using this state.count, it will be updated dynamically, as we can see below. If we wanted to reuse this counter component, how might we do that? Well, do we just keep state and manage it ourselves? What if we had application state that needed to come from somewhere else and provide it to this counter. Let's look at how we can use a term called props to achieve this. Props are essentially options we can provide to our components. They're similar to state in that props can be anything. We use prop types to provide validation and makes sure props are used as intended. We can also provide default props that will be used for props that are never passed. Let's look at how we can take the counter example before and pull it out into reusable piece. Stateless components will receive props as an argument, and stateful components will receive props as a property which can be accessed under this dot props. In this case, we're not passing any props to our app, and so we're only going to worry about the counter and the props that are coming back to that. If we can see that we have a counter component, we're passing props to it called count on decrement and on increment. We hold state though in our app now. We're not holding that in the counter component itself. This counter component is now agnostic of its state and can be used in many different ways. It doesn't need to know where its state is coming from. This is a basic idea of how props work. We won't get into the details of prop types or default props here. But I highly recommend that you go look at the React documentation and read about more of it. Finally, let's look at how we can render things to the screen. Like the React package, there are separate packages for different renderers that we talked about prior. Remember, we said we could render to either a native platform or to VR or the web. Today we're going to be using React DOM and their renderer. That is provided as a separate package. We use the React DOM package, which provides us with a render method, and it's very simple. All we do is take our components that we've been defining, we will pass that as the first argument to render and in the second argument we just pass a valid DOM node. In this case we're going to get the DOM node by using getElementById. This isn't the same as our render method. This actually renders to the DOM. Instead of just updating our components every time with a render, were actually rendering to the DOM and updating the DOM every time this is updated. That was a high level overview of React. We learned how the virtual DOM worked, what it is, how we can use React.create element to communicate with the virtual DOM. How we use JSX which is an HTML like syntax that compiles down to React, create element. Next, we learned how to build components and how we can use state to make things dynamic, and then how we can use props to make things were usable. Finally, we learned how we could use React DOM to render things to the screen on web. Let's jump into a real-world example and see how these things all work together. See you there.
3. Coding in the Browser: CodeSandbox is and online code editor and is one of the easiest ways to get started using React. This is what we will be using today to create our gallery app. You can visit this webpage by going into codesandbox.io. Create an account so you can save your progress as we go along and then come back to this video. Once you have an account or logged in, let's get started by clicking the Open React button. This will create a sandbox for us with a simple React app ready to go. CodeSandbox uses a tool called Create React app developed by Facebook. It gives us a head start when building React applications by taking care of setup and configuration. Traditionally, we would need to set up a server and tooling like babble to transform our JSX to create element like we talked about before. But Create React app handles all this for us. You can read more about create React up by visiting the repo if you're interested, just keep in mind, this is what CodeSandbox is using under the hood to power our dev environment. We can see we start with a basic index.js file. We're importing React and React DOM as well as some CSS file for basic styling. Then we have a simple functional component for our app, which then gets rendered to the browser using React on Render, as we saw in the previous video. You maybe wondering where React is getting imported from. It's actually coming from our package.json file. This describes what libraries you want to use from npm as well as some other configuration options that Create React app uses. If you have never heard of a npm before, it is a JavaScript package manager that helps us use third-party libraries like React. Will come back to this topic in a later video and learn how we can pull in other libraries that we can use to our advantage. If we go back to our index.js file and we save command S. We'll see that we're presented with some other options here now. We can go to Project Info tab and let's rename our application to React gallery. This way we can find it easier when we come back to it in our projects. One last thing to note is if we make some code changes and save our file, we'll notice that the code is reformatted. If I do tab here, push command as, we'll see that it comes back into place. CodeSandbox is utilizing another tool called prettier. Prettier enforces a consistent style across our codebase and allows us to focus on actually writing code rather than how our code is formatted. We're ready to start coding our gallery app. Let's learn how we can fetch data from an API and see a real-world example of how state can be used in React.
4. Fetching Data From an API: Before we can start bringing data into our app, we need to refactor our stateless component into a stateful component. Remember that's the only way we can hold state and update our apps. Let's do class here, we'll call it app, we'll extend from react.component, will provide a render method and will return a simple div for now. We can give it a name too. We'll call between H1. We can call it pixel. Then we can even add a little emoji here for fun. Add this little camera, do command S. Now we're good to go and we have access to state. Let's see what we can do here, we added a state we added image's property. We're using empty array there for now. Let's figure out how we can use an API and point some data into app now that we're ready to hold some state and update it. How do we fetch data from an API? Today will be using a pixel API, since it's open to the public, we won't have to worry about authentication. Keep in mind though sometimes APIs require authentication and need a developer key in order to work properly. I will also add a link to a list of other APIs you might want to use below. In our case, the pixel API is public and we can actually visit the URL we will be using today to get data from. We scroll down here, we can see that they give us an endpoint that we can use. Let's visit this and see what we get back. We get back a list of images. Cool. How do we get this into our app? Well, we can use something called Fetch. Fetche is a method available to us on window and allows us to reach out to a resource and give us back a response filled with some data. They uses a promise, which if you don't know what a promise is, it basically says that we promised to do this thing. We say we're going to do something and then we want to do something else. It's an asynchronous by nature. Instead of thinking how code run synchronously, so you call something, something else happens. We don't really necessarily know one promises going to resolve, Similar to, in this case, an HTTP requests where we want to go fetch some data and get something back. We go down here, we can see that we get a promise that resolves to a response object. Let's look at this response object real quick. The response object contains some properties and methods that we can call on it and we're only interested in one today. Richardson in this body.JSON. We want to call this when we get a response back, which will return another promise. Then finally, we can get our data from that response. Let's go to our app and see how it work. Now we want to take advantage of some lifecycle methods. One in particular is componentDidMount. This will get called when the component first mounts to the screen, so now we can start fetching some data. We'll call fetch. We'll pass it the URL where you can get the list of images from. Remember, this returns a promise, so we can call it then, and we receive a response. That response we can call a JSON method on, which will return another promise. Then we can call them again, and now we actually have data to work with. Open this up into a function. We're just using a fat arrow function here. Then we'll go this set state. We want to change our images now our images property and we will now pass it back the new data that we just got, do command us to save. Now let's see if we log out our state where we get back. If we open up our console, we can now see that we have two objects that we loved. Remember, render gets called when the component first mounts and then if we update it and call this at state or will get updated again with whatever we want. This case we have images with an empty array, which we can see here we started with an empty array images in our state. But there we call this set state with the data that we got back from this API that we had. Now if we log, we open this app, we can see that it worked, we got back all of our images pretty cool. Now we can open this app. It's just an array of a bunch of data, as we saw on when we come back over here and we look at all this data that we got. Now we have access to that, we can do something with it. Let's close this and let's see how we can use this. Now that we have this data, how can we get it on screen? Remember, we can use JavaScript interpolation. Let's open it up here and we'll access images. and then we'll use map because it's a function of array. We can map over each image and do something with it and return a new array. In this case, we will do image source. What can we pass it to the source, where we pass the source? Let's go look at it would pick some gives us back in our API call. Remember we've got all this data back, so what can we pass it to build up an image. Doesn't look like they give us the source of an image, but we do get the ID of each image. This is weird. How does this work? How would we get an image URL? Well, this is how APIs work. Sometimes they give us a little bit of data and then we can use that to build up even more data. So in this case we have the image ID and let's see if they give us a way to get a specific ID. Oh, here, perfect. We can get a specific image by going to this URL and grabbing an image. We'll see how that might work. If we go back to our app, paste this in, renews JavaScript interpolation here. Cool, now we're getting back some images, but it's just the same image. That's not that cool. Let's use some interpolation. We can use our image that we have now that we have access to and we will get its ID. Cool, looks like we have images now, so now we're rendering images on the screen is pretty cool. Doesn't look that nice, but at least we've got our images come in through and rendering to the screen. Let's find out how we can make this a little bit nicer. Before we do though, we do need to add a key to this remember, reactor will complain if we don't have a key and thankfully we have an ID here. Since its unique, we have to understand this and be happy, save that, cool. Looking good. One thing we should do real quick is if we look at our data here, we need to add a slice method because we're grabbing too many photos right now. We're grabbing about 1000 photos, so we should only grab about 30. Let's just do that real quick. Then now we can see that we don't grab as many photos. This will be a little bit easier to load, cool. Now we're ready to start that app.
5. Styling in React: How do we start our application now? We can see we're importing the CSS file here at the top. Let's go in there real quick. This is some styles that were set up before. We don't want text-align center and we're not using app anymore so we can just target our body. That looks good. Now our fonts are using a san serif looks a little bit nicer. If we come over to our index file, now how do we, should we just use a style sheet like before social we go back into styles.css. We can do that, but since react is just JavaScript, we have many different ways in which we can style our applications. We could use inline styles by providing an object, although this might come out of performance cost, we can use traditional CSS by using class name and a style sheet or we can use a term called CSS and JS, which is what we'll be using today. There are a ton of libraries that support CSS and JS that all come with a different feature. But today we're going to be using a library called emotion. Emotion supports for CSS styling abilities in JavaScript. I personally like using objects, but you can also use a term called tag template literals in order to write more familiar CSS in a string. Let's see how it works here. We import the CSS function from emotion. We can build up our CSS string and apply. This will create a class name, and we can apply that class name to our domain. We can see here that we have to install an additional library to use it with react. This is what's cool about emotion. It can work with or without reacts. It works with many different platforms. This is the tag template literals, stuff I was talking about. We can see here that we have an app. We pass a class name just like normal, like we would pass any other class name. It gets resolved properly. We don't have to worry about managing a separate style sheet or anything like that. We can keep all of our styles and co-located together. This is really nice and we'll see how this can work. Let's come back over to our app and start styling it. First we need to install our new dependencies. Remember we said we come back to our package.json. How do we do this in code sandbox? Will it give us a really easy way to do it. We can just add dependencies here with this button, we'll click that will look for emotion and there it is. We'll install that. We see that got added to our dependencies. But remember we're working in reacts, so we need to add the emotion react dependency. Motion react, there is. Cool. We're ready to go. We have back over to our index.js. We can import styled from react motion will see that. Now we're ready to start styling our app inside with CSS and JS, we don't have to go back to a style sheet. I usually like to keep a style sheets still so I can manage my global styles. You can do this with emotion, but it just depends on what you want to do. I like having just a regular CSS file for global styles and using the CSS and JS to keep my other components specific styles co-located, which is really nice. Motion gives us this styled function. We can start using it right away, do style, and then we can pass it a string for whatever tag we want to use. In this case we want to use a header tag. Then we'll pass another function with an object, and that will be the styles that we want to give it. We'll do some padding to make it look a little bit nicer. Give it 16 pixels of padding. Then we could do back around color, I like to use HSL, that's hue saturation and lading. It's just an easy way to remember your colors without really having to look at them. We'll do zero percent for saturation and then lading we want to do we'll do like a darker or like a light gray. We'll do 94 percent. We'll see how this works. Now we have this component that's been created for us and the style, the class name has already been created for us as well so we don't have to worry about going to a style sheet. Everything's right here, which is really nice. If we go down here, will wrap our title into a header and then let's see if it works. There we go, you can see it's a little light gray, but we have some other styles that are clashing. We have default margin in our body so let's get rid of that. This is just from the browser's default styles. It looks like our H1 is inheriting some style. This is why I like to just maybe clean things up. We could even important normalize or something here to reset all of the styles. But in this case we'll just do it ourselves and will do no margin on our header. Well, now it's looking a little bit better. Now let's get our photos and put them into a grid and make them look a little bit nicer. We can do const, we're going to call this TileView. Then we can use our styled function again and this will just be a div now. Then we'll pass another function with an object and we're going to use display grid. Then we want to be able to pass props to this style element. Maybe change it make it variable so we can change it based on different options. What's cool about emotion is it allows us to pass on props here. We're going to wrap this object in parens because we want Implicitly return it. Otherwise they think we want a function that we need to do a return. Then we'll ask them often will say padding, props spacing, and then we'll do grid gap. Props start spacing as well. This will add spacing around all of our grant or see if this works. We can just take our time view, come down here. We'll wrap all of our images in there and see if it looks like it's working, we'll save that. Don't look like it's working out. Let's see what's going on. We're not passing spacing to it. Maybe this is where we can introduce default props. We're not passing any props to up, but maybe we weren't spacing to be a default prop. We can go here and we can do TileView. We have this component and we can access the property default props on it, and now we can pass spacing. We can say, away 16 pixels as a default spacing. Cool, now it's working. Now if you don't pass any spacing it, we'll just default to 16 pixels. Otherwise, we can come in here. We can say spacing, maybe something outrageous like 60. Well cool so it's working. That's too much spacing. We'll just stick with the default spacing that we set up. We can actually inspect this and see that it's working and how emotion turns everything into a class name. It's pretty cool. We see here, we see this little class name that we get, and it resolves right here. We do get displayed grid padding 16 pixels, grid gap 16 pixels. Pretty cool. Let's add some more stuff to clean this up. CSS grid is extremely powerful, so let's take advantage of it. We can use something called grid template columns. Then we'll pass a string template literal, and we can say repeat. We're going to go auto-fill. Then we can use a minmax function in CSS. Will go interpolation here and we'll say props. We could go min cell width. We're going to have just one fraction. Basically what this is saying is try to fill the viewport with as many cells as you can, but keep them at this minimum cell width. What's really caused we get a responsive feature by default. We don't have to worry about setting up breakpoints or anything like that. We'll pass a default minimum cell with. We'll go 3-20 for now. We also have to remember that we need to pass it a pixel value. So while pixels here, let's see if this works. For recess of viewport should have cells in it that got a stack. Cool. There we go. It looks like it's working. Still need clean up our images, we'll do that next. But now we've got some auto responsive design going, which looks pretty cool. Let's clean up our photos a little bit. They're not fitting in the viewport very nicely. We'll create another component here. We'll call it photo equal to styled. They want to pass it in image. Now pass out a function again with our styles. We're going to go with 100 percent. We also want to do displayed block. If you don't do display block images have the inline by default and how this weird margin on the bottom of them, display block helps with that. We'll go object fit cover, which this will make sure that the image is span like its own little viewport that it's in so the cells in our case. We have that component, let's go down here. But we also should change our min cell. Well that's a little too big. I think our viewport is about 300 right now, so we'll set it 240 that might be a nice width. We'll go down here. We'll replace this and it should just work cause it looks like it's working. These images are a little long. Let's do a square image actually so will replaces with, we'll do a thousand so we have some nice quality. It's nice about the pixel API. It allows us to crop images really easily. Now got some square images. We're looking pretty good. Our images in a row. They have some nice spacing around them. Let's figure out how we can make this little interactive and maybe click on it to expand the view and show some additional information.
6. Adding Interaction: Before we move along here, let's clean up our files a little bit. They're getting as far as getting a little bloated. We can clean this up by moving an intuitive from file. First, we'll just copy everything. This is what I do, I always copy everything and then create a new file. We'll call components. Now, depending on how many files you have, maybe you want to create a folder with more files inside of that. But in our case, this is pretty simple, so I will keep it pretty simple. We only need styled, and then we can see that. We also want to export these all, so this is how we can grab them. Then we'll explore cost TileView, and then we'll export photo. Now we should be able to import these so, you can get rid of all these and we'll get some errors, but that's Okay. We're going to import the files now. We don't need styled anymore. Now we can go to import, and we can pick out these individual components that we just exported, so we'll say for components, and then we'll go Header, TileView, and then photo. Looking good. Let's go back to our components file. Now we want to click on a photo and have it expands, so how might we do that? Our galleries a little big now too. We see if we can shrink this down just a little bit, so we'll go maybe 120. There we go. Now if we open this and close it, yeah, there we go. We get a little bit better view. When we expanded, it actually makes sense. Now we want to take this photo component and we're passing props to it, but I'm actually not even using the props right now. When we create our styles, I like to pull my styles. I like maybe I wouldn't a style sheet and so will say, we can say thumbnailStyles, so this is when it's small. Then we'll do fullscreenStyles as we call it that. That will be an object of styles as well, so we want them to be by default the ones that we declared, so thumbnail is this one. Then when it's full screen, we're going to make the position fixed. Top zero, right zero, left zero, bottom zero. This will, when we expanded it all poured across the whole viewport, we want to give it a minimum height so it's not too big. We'll give it a little bit of breathing room, so we'll do 80 viewport height, and then we can also do margin auto to center it in the screen. Now, we can take these styles that we just defined and we'll get rid of this. We can say, since we get props back, we'll say props, we'll call this prop isActive, and you can say if it isActive, we want to use the thumbnailStyles, but we'll use fullscreenStyles when say active, and then otherwise, we'll use the thumbnailStyles, so we can save that. I think we're good to go now. Nothing will happen or absolute looks the same, so that's good. Let's figure out how we can tell a photo to be if it's active or not. We can introduce some new state here since we want to change our app when we click on something, and so we'll say, we will hold a currentPhotoId, that'll be null by default. Then in order to determine if something is active, we will do, is active in this state currentPhotoId equals this image.id. How do we get currentPhotoId? Well, remember we talked about onClick so we can pass an event. We could say onClick, and will pass a function, and then we'll see this setState, and we'll get the currentPhotoId. We'll set it to this image.id that we click on. We're looping through, we're attaching these events and we're seeing, when we click on this photo, we want to set whatever photo we just clicked on to the currentPhotoId, and then now we'll update our state and come back down, and so every time it goes through each image, it'll say Is this one active? Is this one active? Is this one active? Finally, it'll get to wherever one we had clicked on, which is set to the currentPhotoId. Let's see if that worked. It looks like it's working, so now we can click on some photos and expanded and this doesn't look too good, but we'll fix this here real quick. How might we close this? When we click on a photo, nothing else happens is just going to keep setting it to the image ID, right? So we could say here, we could pull this out again. This maybe when you want to pull this out into a function up here. Sometimes I do that rather than doing an implicit return, we'll do an explicit return, so we'll return this. Now we can store variable up here called isActive, and then we can say, we will pass isActive down here now, so we're just going to clean things up a little bit. Now we can say, if we're isActive, we want it to set to no, rather than set to the image. Id, so that should close the image because it will just go back through no and then now it won't be set any longer, so we'll save that. Now we should be able to click on a photo and then click on it again, and that now works, so it sets it back. Let's see how we can clean up our styles a little bit and make it look a little bit better. Next, we want to add a frame components so we can see our photo a little bit better and we don't have a destruction behind us, so let's do that. What are the components? Will do export const Frame equals styled, and this will just be a div and will pass its own styles when you use a similar styles here for, as a full-screen styles, we'll just paste those in. We're going to do background color. In this case, we're going to do each hsla, which is an Alpha channel. This is really weird. This is what I don't like this in the hsla and hsla, but we have to use commas now. Just always remember that if we're using hsla and each hsla that we have to use commas with the hsla and not commas with the hsla. It's a little confusing, and so what the zero percent, we want a 100 percent for white. Then we're going to do an Alpha channel here, so it'll give us a little bit of transparency. We'll do 96, so that should be good for our frame styles. Will save that copy of frame and back to index, will import it, and then we'll just stick it here at the bottom. Since this position fix it should just show up. How do we get this to show and hide? What we can do some cool stuff here with. Remember we are just, we can interrupt with JavaScript. We can say this.state.currentPhotoId and if it since null is true, the IRF is a falsy value will say, if there is a currentPhotoId, show this frame. Otherwise just don't show it. This would evaluates to true, and then it'll just run this which would be create element and render our frame, so save that. Now when we click, we should have a frame that pops up. There we go. This is a good reason. Even though currentPhotoId are null is falsey, currentPhotoId cant be zero. That was what we saw when we clicked on the first one. Come back over here and we'll say, does not equal null. Sometimes you can run into a problem like this. Just watch out if you have something where you're comparing it and it's zero, then it might not be true, so we click on this. That should be good. Can now we don't see our image anymore. Let's get that to show up. Come down here, why zIndex because right now this is sitting on top, basically because it's sitting the order of the DOM and wished sets, so we'll say that this is the zIndex of five. This is where we start playing with our zIndex words, right? And then cIndex is 10, so now we click on it. Now click on it. We see we have a frame behind us. We can click on and close it, open, close. Pretty sweet. Let's clean up styles a bit for this photo. Maybe, height 80 viewport wasn't good. Lets do width here, we'll do width and we'll do 80 viewport width. There we go. We're looking good. We add one more thing here. Let's see if we go to props is active, let's just add a cursor here, so we'll change our cursor when we're hovering over and will say, and it's full screen, we want to zoom-out, and then when it's a thumbnail, we actually want to zoom-in and see how that looks. Well it does it.
7. Conclusion: We'll learn how to fetch data from an API, how styling works and react. How we can build prop APIs around things like CSS grid. How to add some interactivity by clicking on an image and expanding it.I wanted to keep this lesson short, but remember there is a lot more we could do with this out.If we open this image,for instance, it's a little big.We can measure the viewport and make sure the image always fits or at proper accessibility by hooking up keyboard controls or even add some nice animations. I highly encourage you to go above and beyond in your projects if you're up for the challenge.This was a pretty high level overview of what is capable with React.I encourage you to keep reading through the React documentation, learning vanilla JavaScript and taking react courses, please post your projects and we can work through any issues you have together. Thank you so much for taking this class. It's been a pleasure giving you some insight into how React works and how we can use it.I can't wait to see what you create.