Transcripts
1. Welcome to the course: Welcome to the React Academy for beginners. In this course, you will learn everything you need to know to get going with react, to build user interfaces. All our builds in a real project, put your new skills into practice. Throughout this course, you will be building eight fellow inspired application, which really shows you what you can do with react. We build falls to group together your ideas and organize them with lists and cards, all while making news of react components. These are also editable, you can click on them to change the names and also the cars have a pop-up model where we can change the contents and also add or remove any labels. This app gives us the chance to understand react concepts such as passing data with props, working with state, forms, routing, component types, and life cycles, custom methods, and so much more. This course is beginner friendly, so if you are new to react, we'll go over all the basics you need to get started, and then step things up throughout the course to give you a deeper understanding of react. Although we should already have a familiarity with HTML, CSS, and basic JavaScript to get the most out of this course, we will not just be building the front-end of the application either. We'll also make use of Firebase to create a back-end for our project too. This will give us a real-time database to store all of our data. It will persist after a user returns and also any changes we make, such as add-in, removing or update in. We'll update our application in real time, meaning changes will take effect right away without needing to reload the page. We also enable users to sign up and login to our graph. This allows users to have their own personal boards, which only they can see or edit. Along with learning about things such as conditional rendering, documents, snapshots, authentication, salting, and filtering, listening for changes, and also the React contacts API. We round off the course by learning how to build your app for production and finally deploy for the rest of the world to see so if you were interested in learning React and want to build a foreigner project along the way, enroll in the course, and I will see you in the class.
2. What we will be building: This course is completely project-based, meaning we're going to be building this Trello inspired application right from the beginning of the course to the end. We're going to be adding to this step-by-step, as we learn more about React and Firebase during the course. We're going to put it into practice everything we'll learn about React straight into this project so you can see it in practice. The project which will build on throughout the course is going to be inspired by Trello. If you've not used Trello before, it's basically an application which will allow us to organize things by creating boards, which is a board for a certain subject where we can add lists and cards, we can list ideas, we can create labels, and so much more. In this application, we're going to begin on the home screen by allowing users to login with a e-mail and password. The authentication will be handled on the back-end using Firebase. This will give us a secure login and sign up facility, where users can then register. They can then create boards. For example, we can set up our ideas for summer. We can create this board, we can give it a different background color, let's go for green. We can create this board. This is now saved to the back-end database, which is provided by Firebase. We can then go into our board, we can create new lists to section our content. For example, we can say places to visit and also create a new list, things to do. Each one of these lists can have individual cards, and we can add as many of these cards as we like. Let's say visited Paris. We can then click on this edits. We can edit the text, we can add labels, we can remove them by clicking on them once more, we can then save our changes and this are then displayed in inside of each card. We can add cast over list, such as paint house. This can also be clicked on and edited. We can add various labels, save our changes, and all of these changes are pushed immediately to Firebase and then updated in real time in our application. This means that we don't need to refresh our application to then get the data back from our back-end. This is all immediately updated, as you see here. We can also delete our cards, our lists, and also our boards, and these all link together too. For example, when we create a new board, list, or card, these all created by a certain user. The user ID is stored into each one, meaning for example, if we go into one of these boards and then we delete this, this will also delete the corresponding lists and cards which are linked to each board. We can also log in with multiple users, and each user will only have access to their own boards which you have created, and you can see this if we log out and then log in as a different user. Click on the login button. Then we're redirected to our board's view where we have a different set of boards created by this user. Let's add some example list inside here, and also boards. These are completely independent to this user. This is going to be the application which we're going to build during this course. This project will allow us to demonstrate everything you need to know about React to build applications, we'll also learn a lot too about Firebase, including the real-time database, authentication, getting updates in real time, and then finally, at the end of the course, we will make our site live, where we'll push this to production for the rest of the world to see. I hope you're as excited as I am to get started with this course. In the next video, we'll run through a couple of things which are needed for this course before we then jump into the next section where we start working on this project.
3. What you will need for this course : To get-go, there is only a few things which you will need and the fact that you are taking a tech course probably means you already have some of these anyway. First of all, I will be using Chrome as my web browser but you are free to use any which you prefer. However, I would recommend either Chrome or Firefox, since the React developer tools, which we'll be using is only currently available for these two browsers. To get the developer tools, do a search for reactive tools and as you can see here, we have the options for add into Chrome or also to add to Firefox which you can find from this link here. I recommend you go ahead and download these for either Chrome or Firefox, and it will really help throughout this course. Next, we have the node JS download, which is available from nodejs.org. We won't be using node as a back-end or a Web server, but it is needed for a lot of the tool in which we use when developing locally. Go ahead and download the latest chrome conversion for your operating system and then click "Next" through the installation. We also need a text editor tool, and I'll be using Visual Studio Code, which you can download from code.VisualStudio.com. You can use others if you prefer. But this is one which I really like and I will be using throughout the course. It also has a built-in terminal, which works well and we'll take advantage of this when building our projects. Again, any terminal is also fine to use if you want to use something different. But for this course, I'll be using the one built in to the s-code. If you would like to use this, I recommend you go ahead and download for your machine and then go through the usual installation process for your computer and then this is pretty much all we need to get going. Anything else we need to use such as any packages from MPM, we will download as we go through the course. Let's now move on to learning all about React in the next section.
4. Create React App: In React earlier days, creating a new project involved a lot of setup work. We had to install and configure tools such as bubble and Webb Park and the setup time could put off a lot of beginners. Now we have a great tool called Create React app, which is a really quick and simple way to get started with react without getting caught up in all of the initial setup and configuration and it's also officially supported too. We use Create React app from the terminal, but it's only a few commands, so don't worry, if you're not a regular terminal user. In fact, we can even use the one provided in Visual Studio Code. Let's open up Visual Studio Code. If we go to terminal and new terminal, if you also have a separate terminal which you'd like to use too, this is completely fine and it's no problem in doing so. By default, it will open up in the home directory. We can use the CD command just to make sure, so type CD then Enter then we'll take it to your roots user directory. We can then type LS. This will then give us a list of files and folders for the user. Notice the desktop here and this is where I'm going to be adding my projects. I'm going to CD into the desktop and hit Enter. You can create this project anywhere on your machine which you prefer. I want to keep this on the desktop for easy access. Then we want to run the command NPX, create React app, separated by hyphens. Then the name of our project, which I'm going to call reacts Trello and then hit enter. This might take a little while to run since it needs to pull in all of these scripts, dependencies and modules for react to run. Notice the NPX command at the start rather than NPM. NPX is a tool designed to easily install and manage CLI packages. It basically allows us to use Create React app, just this once without needing to install it on our system. Give us a few minutes to finish off and then pause the video and I'll see you when this is finished. Okay, so once this is all installed, we need to change in to our project directory. We can do this by either typing in CD react Trello, as it says in the terminal, or we can drag over the project from our desktop. Grab the project folder, drag this over and then open this up to drag this into Visual Studio code. You'll see this automatically opens up the terminal into our project location. You can now go ahead and start the development server. We do this with a command called NMP stars. Type this in and hit "Enter." This will then setup the development server on localhost 3000. This will either open up automatically in the browser or can navigate to localhost 3000, just like this, hit "Enter" and now have a basic React app up and running in the browser. This is why we need to go to view our project in future. Unless you are running on a different port. If you want to make any changes, all you need to do is to go into the text editor, then into the source directory and the app.js. Don't worry about all of this code at the moment, let's just go down here into the p elements and say, "I'm learning react" save this. Saving this file will automatically cause the browser to reload and update with our changes, which we just added in. We don't need to worry about refreshing the browser after each change. That's it now for our project setup. Next we'll go over what all of these files and folders are which have been created for us using Create React app.
5. Project files & folders: Just before we go any further, I want to give you a quick overview of what online files and folders are in our project, since they've been generated for us using Create React app. I don't want to just assume that we know what's going on here without going any further. First of all, at the very top we have the node modules folder. This is where all of our projects, modules or packages are stored. This directory is nothing specific to react. This is typical of any node projects. That require lots here if we open it up, and this location is also where any of the packages which we install will also be saved. Later in the course, we'll download packages such as Firebase and React router using NPM. We'll see these saved inside here. This is also where our actual reacts package is saved to. If we scroll down, there's quite a lot we need to get down to react, react Dom, and also the React scripts, which we'll take a look at in just a moment when we get to the package JSON. Next, so we have the public folder. The public folder contains our static files, such as any images we want to use, and also any HTML. React has this index.html file. If you open it up, scrolling down to the bottom, that is not a lot of content inside here. If we go over to our project inside the browser, and then go to view page source. This is the page which you see inside here. It doesn't show any actual HTML content in here. Even though we see something in the browser. This is because of the script tag down at the very bottom, which is this one here. Remember earlier we said that Create React app, takes away the configuration photos, so we can concentrate on creating our React app. Well, this is one of the things which it does. It will use web pack to bundle together all of the files and assets we have in our projects. Then create a bundle file as the output. This file is then injected into the projects using the script at the bottom. It injects them into any DOM element which we choose. Currently it will be output just above the div with the id of roots. This is one just here. We can click on this bundle link, which is the last link just here, and open this up into a new tab. This is all of the contents of our bundle. Don't worry about everything which is inside here at the moment, it's all just generated code for development. If we do a search, so browse search of command or control F, we can search for the text we added, and we search for, "I am learning reacts". We see this text is down here. This HTML file can also be used to add scripts or phones too. But this can also be often added as node modules. The next folder we have is the source and this is where we will be spending most of the time during this course. It's where we'll add our raw code, all of our JavaScript files on components. All these will be included into our bundle, which we just looked at. This is how they make it into our final app. There is no strict structure on how we can do this. We are pretty free to organize all files and folders how we like. Although it is common to include a components folder into the source directory, we'll do this soon. We will get plenty of practice writing components too. A component is basically a block of code, which we'll look at in more detail very soon. Next we have the app.css. This is a main CSS file which contains some default styling. In React, it's quite common to see a structure like this, where we have one CSS file per components, and in the case here is the app.js. This app.js is one where we made our changes in the last video. Again React is pretty flexible with things. But this is often used as a main top-level component, or a wrapper for the rest of our project, we will be using this file to display our header as this will be on all pages and then below where we use a router to switch between different components depending on the page we're viewing. After this, we have the app.test.js. This is a file if you want to test into our React project, although we won't be covering testing in this course. Next we have the index.css. This is a second CSS file containing these styles relating it to our index.js. Again, this is just for separation and organization. I'm going to delete this file to keep all of the styles nicely together in one file. It's a tube, I'm going to remove this, and then open up the index.js, because we deleted this file, we also need to remove this import from the index.css, and save this file. This is a main JavaScript file which is going to be responsible for rendering our app, the browser. At the top, we importanting both React and also ReactDom from our node modules folder. In React early days, used to be in one large react package. But since it can now be used to build mobile apps with React native or even VR apps. All of the core functionality is now stored into this react module and any functionality related to web apps, is now in its separate import called ReactDom. ReactDom has a random method, which we say just here, which is responsible for rendering the contents to the DOM. This random method takes in two things. First, we have the contents which you want to display, currently our main app components. This is the main route components, as we mentioned before. It's often used as the project wrapper. When using this in a file, we also need to import it over the top, just like we see here. Then second of all, the location where we want this app to mount two. I saw this onto a new line, which is currently set to an element with the ID of roots. Which is what we looked at earlier before in the main index.html, the public index.html. This is the div with the ID root, which we've seen before inside the browser. So this is basically saying, "Take my React app and place it here where we specify in the index page." The reason we do this is because we don't always use React for our full application. We may already have an existing projects, where we only want to use react in a certain part. For this case, our HTML page may have lots of existing content and we can simply add in a new element to mount react to. You can change this up to be anything which you want. We can add in some js X code. Lets add a level two heading, a title of React Treble. Then close this off. We will look at this js X code in more detail soon. But it is basically a syntax we typically use in React, to mix both HTML and JavaScript together. If we save this file and then go to the browser, we now see that our Level 2 heading has been mounted to the DOM. If we reload the view source, we still see that we don't have the contents. All we have again is this div with the ID root where our React app has been mounted to. Let's just change this back, to our app components. Next up we have the logo.svg, which is provided for the Create React app's data, and then also a service worker file. This is an optional file to register a service worker. We won't be covering the service workers in this course, but they used to make your app work offline, often to enable things such as push notifications. If using GitHub, we also have a dot gitignore file already setup. This is used to exclude any files which you don't want to push to GitHub, such as any sensitive information, containing passwords, or any large or unnecessary files such as the node modules. Below this, we also have the package.json. This file again is not specific to React. It's something which you will see on a regular no projects. It contains information about our app, such as the app's name, the author, along with any dependencies which we'll need for the projects. Inside of the dependencies, we have the react-dom listed, we have react and we also have the react-scripts. React-scripts is a library used by Create React app, and includes all of the scripts and configuration we need to run react in the browser. It converts the dependencies we need, things to chance, bubble and web park behind the scenes, and then bundled them all into one library. This also makes maintaining all these packages much easier, since we just have one library to worry about when upgrade him. These dependencies in a no project would be added to our node modules folder, after running a MPM install commands. All this is also being cupboard for us when we set up the project, below our dependencies, we also have some scripts. We already use the start script with MPM start kick-off our project at the beginning. There is also a command to build our projects for production, one for testing. Then we can also eject from React scripts. We've talked a bit so far about how a lot of configuration is to influence behind the scenes. However, we can use this eject scripts to go over all of these hidden magic and then place copies of our configuration and dependencies, such as web pack and bubble, and then place them directly into our project so we can edit these ourselves. There is also some more information about this in the readme file too, finally have a yarn.lock file, we don't need to worry too much about this since a is autogenerated, and contains a list of our dependencies and exact version numbers which we are using. This is for our file and folder structure. We will get a lot more familiar with this as we build our React app. Next we'll take a closer look at using components.
6. A closer look at components: In the last video, we mentioned the word component quite a few times. If you're still not sure what a component is, we are now going to take a better look at what they are. A component is a typical small part of your website, which you can group together and place in it to its own file. It can also be reusable. If we had a blog, for example, component could be a blog post. This blog post components would then be re-used for each post which we have. Even though they are reusable, we can still feed data into it to make them dynamic. We could feed into blog components, a blog title, a blog text, and also an image. To see a real world example, this is the project which you will be building in this course. Using something such as static HTML, we'll end up with a lot of duplicate code. Each list, which is the free sections of garden, bedroom, and kitchen, and also each one of the individual cards on the list would need its own HTML markup. This would mean a lot of duplicate HTML code. However, the React way is to break things up into smaller pieces called components. At the top, a header is a component, and we're going to store this in a Header dot js file. These components can also be rendered on every page, avoiding coordinates into each page, as we would do with regular HTML. Below the header for this page, we also have board components in a file called bought Board dot js. A a user can have multiple boards, so these components can also be reused. It is passed in data called props to allow things such as the board title to change for each view. In this case, the title is house. Nested inside of this board, we have a list components. Again, we have one component rendered for each list in our database. This is another good use for a component, since we can again reuse it, and then passing data or props to each one, such as the title and the functionality to add a new card. Next up, as you will have guessed, each card is a component too, receiving props such as the text and also the labels. Each time a new list or card is added, the component will again be reused. Everything we see here is a child of the main App dot js components, which we looked at earlier. This is how components are used in React. There is no hard and fast rule to when some things should be made into components. It's something you generally have to figure out for yourself as you create a project. As a very general guide, we should use components if something will be reused or to group together related functionality. There's also occasions when a file is getting too big. This can also be a case for breaking things up into smaller components, too. Now, we have an overview of how our components will look. Let's get to work on creating them in our projects.
7. Components in action: Back over to our project, I'm going to create a components folder in the source directory. In the sidebar, let's create a new folder called components. This folder is purely for organization and is not a requirement when using react. We can also break this up into sub-folders two, and we'll do this later in the course. For example, you could have a header folder inside containing all of the header components and so on. If we wanted to, just to keep our files more organized. Next, our three components, which we looked up from the slides are board, card, and list. Inside the Components directory, create a new file. The first one is going to be Board.js, uppercase B. Again in the components folder, the Card.js with capital C. The third one is for List.js with a capital L. It is a common naming convention to begin a React component with a capital letter. First of all, let's go over to the Board.js. For each components where we use react, we first need to import the React package from the Node Modules folder. We can do this with import React from React. React here being the name of the Node Module. Then this one is an alias which we're going to use in this file. Even though we are requiring React every file we use, it's only included once in the final build. We don't need to worry about multiple copies in our project. Also, if we just add the module name, just like react, rather than using a file path, it will be assumed that this is stored in the Node Modules folder. Next, we need to create a class which looks like this. The class name of Board extends React dot Components. Then open up the curly braces. This is a typical React class-based components. Later on, we'll also look at another type of component. But for now we're going to be using a class-based component as it has a few extra features which we'll get into. Then at the bottom after these curly braces, export default, another name of our class which is Board, export in this components will then allow it to be imported and reused in other files. Above we are extending or inheriting all of the properties from React dot Components. React dot Components will give us access to various optional methods, such as life-cycle methods, which we'll get into soon. But the one which is required is the render method. The render method, as it sounds, is one which we need to render some JSX to the browser. Let's add the random method inside here, which is going to return some data. The data we're going to return is going to be some simple JSX code. Let's add some HTMLP elements with the text of board components. If we save this file and then go over to the browser, and we don't see any of the board components on the screen. To be able to see this, we need to tell React where we want this to be placed. Let's go for the parent's app.js, since we've exported this board components down at the very bottom, we can now import it into the file where we want to use it. We're going to do this in the app.js, need to import our board components. Since this is not a Node Module, we also need to specify the file path. This is inside of the components folder and the name was Board. We don't need the dot js extension since this is assumed. We can then place this board components exactly where we want it to display. Let's go and place of the text which we added earlier. Slash remove this and then the name of our component which was Board. This is a self-closing element. Which means add the forward slash at the end. This is how we can place a component into our code using React. It just looks like a self-closing HTML tag, such as an image. As a quick side note, you may have noticed this app.js file has no render method. This is because it's called a functional based component, and we'll take a look at these later on. Let's save this file and head back over to the browser. We can now see our board component is playing in place of our text. You can also now do the same for the list component too. Back over to the side bar, go to the List.js. Just as before, we need to first import React from react. This is also going to be a class-based components which is going to be called List. This will also extend React dot components. We can then use all of the methods which is provided by React. Inside here we're also going to add the render method to display our JSX on the screen. We are then going to return some JSX inside here. Just like before some simple text will do to just list component. Then right out at the end we also need to export default, the name of our component, which is going to be List. This will be nested inside of the board components. You can import it inside of the Board.js, save this file and head over to the Board. Right at the very top we're also going to add an import for our list. Again, since this is not inside the Node Modules folder, we also need to add the file path. This list component is alongside the Board, so we'll just add a slash and then the name of list. The final step for this to display is to go into our render method, and then we can add it as a self-closing element. List, as we already know, components are reusable, meaning we can add this in as many times as you want. Let's duplicate this, and let's save this and go over to the browser. I'm see an error inside of the browser. Generally, as far as error messages go, React is pretty good at letting us know where the problem lies, and giving us a hint on how to fix things. The error message says, "Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment?" We will look at this JSX fragment soon. But this error is basically caused by a component not having a wrapper over in the Board.js. In our render method, we are returning three different elements. All these three elements are effectively side-by-side. When using React though, a component must have one parent element as a wrapper. It can be any element which we choose, but a div here would be fine. Let's add a div, opening tag at the top. We can move the closing tag right down to the bottom, and then nest inside our three elements. If we now save this and go back over to the browser, we see a error. This should be extends with an S on the end. So to our list. There we go. Save this and then over to the browser. Now we'll see our board components and then nested inside we have our two lists components since we added this into our render method twice. We can now move on to the card components, which will also follow a similar pattern to the board and list. We first import React at the top from the Node Modules folder. Then we can create a class-based component. Class Card extends React dot Component, we curly braces, and then we can add our required render method, which is going to return some JSX. Just like before we'll also add the p elements, simply outputting the card components. Then don't forget, down at the bottom, we need to export this file so we can use it in other components. Export default, the name of our class, which is Card. These cards are nested inside of the list component so let's import it over in the List.js. We can import this. Now the top of the file. This is also alongside the list, so we just need the dot slash and then the name of the file, which is Card. Now down in the render method we are putting in the p element that just cut this out, and then we can add a surrounding div so we don't get any error messages in the console. We can paste this back in and then add inside as many Card components as we like. I'm going to copy and paste this in three times, then over to the browser. Now we'll see our board component output once. We then have our two lists components, which is this one and also this one because we outputted the list two times here. Each List components then has three Cards nested inside, which is why we see so many components on the screen. If we go over to the developer tools, we'd right-click and then inspect. Inside of the Elements tab if we look at the HTML structure, we have a surrounding div with a board component nested inside. Then we have a full div, which is for our list, which contains the three card components inside. After this we have a second div, which is for our second list components. Again, this also has our three card components inside. Also in the console we'll see we have some error messages. If we go to the top, we see a p elements cannot appear as a descendant of p. This is because of the way we structured our components. If we go to the main wrapper, which is app.js, we have the outer Board components nested inside of these p elements. We can just move this up outside. Save this file so it appears along side the elements and now we have no more areas inside of the console. Now we'll have our first look at how components work. Now we're going to step things up in the next section, where we'll begin to work with data and also pass it to components.
8. First look at state and JSX: React is a front-end view library, therefore we need some data to work with. Later on, we'll be focusing on using Firebase as our backend to save unretrieved data. Both at the moment, I'm going to be using some sample data to work with. I have provided some sample data, which you can download and use for this course, which I have here saved to the dashboard. Let's start by creating a new file in our project. Install this sample data, we want to add this in the source. Create a new file. I don't want to call this the sampledata.js. If we open up this sample data, we can then copy the contents by selecting all. Then copy and paste this into our sample data file. This is simply some data, so we can work with components. We have a board's array, which is simply three different boards which you can live through. Below this we also have some lists. These are linked to the board by the board ID. They also have an ID and title, and then it nested inside will have some individual counts. This will now give us some basic data to work with in our components. When using react, the current data which have no components, is referred to as state. State is an object on a component which contains data which can change. For example, will be using the state in the list component to store all of the Quran cars in that list. State is independence of each component two. We had a free lists, just like we have here. The state will be different for each one. Since all of the car data is different, the state of the garden list would be an array of cards called new table unfixed fans. The list components for bedroom one would have a state array of new furniture, paint walls, and so on. Another useful parts of state is that it is dynamic. Meaning if the state changes, such as when a user deletes a card, it will update all of the components which uses data. State can also be anything such as if the use is currently logged in, if a pop-up modal is currently open, or the number of likes a post has. To take a first look at state. Let's head over to the app.js and we'll come again to add our state objects. Just after the line of function up. We can create our state object. Then inside here we can add any state which we want. Let's begin by adding a bold title and set this equal to a string of house ideas. This state can contain any names and values of the data we want. But remember, this is just the initial states and it can change or be updated at any time. If we save this file and go back over to the browser, back into our project. We see in the error message of state is not defined. This is happening because states can only be used on a class component. Remember before when we created the board listing car components, we created this as a class. Whereas if we go to the app.js, which is automatically generated for us, we have a function base components. This function component is great for a simple function which just takes in any data as a prop. We'll look at props very soon. Then it renders some content to the browser. Allow it just to confuse you even more with react version 16.8, they did introduce something called Hooke's, which allows us to do more with function components, which we couldn't previously do. But that's not something we need to worry about just yet. So to add state, what we need to do is to convert this to a class based components. This is just a few simple steps. The first thing I'm going to do is to clean up this return statement and remove all the unnecessary code. Let's take out the header and also the class name of App. Give us a save, now we'll just have a empty div inside of our return statement. Now we need to replace this first line of function App with a class just like we did in the board. So we need to expand the react components. Remove this. This is a class-based components which is call App. This will go into extends, react all components, making sure we still have the curly braces surrounding all of this code. Then as we mentioned earlier, a class components needs to have a random method. We need to surround the return statement with this. If we could just return statement out, we can then add in the random method inside the curly braces placed in the return statement, save as file, now should see no errors inside the browser. Back over to our state in the app.js. We can access our state using the curly braces inside the div. Let's add IP elements to output our states. The curly braces. We can access state with this dot state. Then the name of our state called all title, gives us a save, and then over to the browser. Now how the board title of house ideas. First of all, this is what is called JSX code, which allows us to mix JavaScript into our HTML elements. These curly braces which surround the states are used when we want to jump into JavaScript, and then run the code inside. We can add any JavaScript we want into these curly braces. So we can do some simple JavaScript such as 5 plus 10. Then we see the value of 15. All we can do is something such as a console log. Let's just add a string of hello. Save this, and then we see the value of hello in the console. Now, let's remove our console log and the 5 plus 10. Now we're going to update our state with the value of our sample data. Well, how would we go about updating or setting the state? Well, we can do this with a method called set state. First of all, let's import our sample data. We can use this in the file. Import data from a string value of dot slash, and then sample data. Then we can set up our initial board state to be an empty array. Let's change the board title to be boardT. Save this be a empty array. We can obtain this with a custom method outside of the render function. But render, we can create a custom method called Update state. We'll call this in just a moment from a button. But this is going to be a ES6 arrow function, where we're going to update the state with the set state method. We can do this with this dot set state. These points to our current component instance. The state that lives on this component's state is an object, when it's passing the curly braces. The state which we want to update is this boards here. At boards, and I'm going to set this equal to data. Though boards, data.boards is our sample data which were important. The next step is to now create a button in our random method to then set the states. So inside relative. Let's create a button. Inside here we can add a click listener. We'd on-click and set this equal to this dot update state, which is the name of our method. On-click is a way of handling the event very similar to a regular JavaScript event handler. Just on-click, on-change or on-mouseover. With regular JavaScript, they are all lowercase names. However, when using JSX I must be camel case, just like this. Every word after the first one begins with a capital. When this button is clicked, we then call our custom update state method in the curly braces, which we'll go ahead and run the code inside here. After this, we can then do a console log to check the value of state has been updated. This is JavaScript. This goes in between the curly braces and in fact we'll do a console table. It's by a formatted. We can then output this dot state, dot boards. Now let's check this out over in the browser. We have an error updating states needs to be a colon. Rather than equals satisfy colon. Then reload, click on our button, and now see a table with all of the three pieces of information from our sample data. We have the free course titles, have the background, the ID, and the index number. This is how we can update our state object using the set states. We shouldn't be tempted, however, to set it in any other way, such as this..state,.boards is equal to some value. We have used this set state method for various reasons. Setting this.state,.boards just like this, will not trigger a component of dates if the state changes. It can also be less performant too. Since multiple set state calls can be batched together into one single update. Slash, remove this. We'll get a lot more practice updating state during this course. Next, we will look at how we can loop through this data, and how to set the initial state when a component first loads.
9. Component lifecycle and looping: Having a button like we have here to load our initial state is not something which is very practical for this use. We need a way to set the state as soon as the component loads, and we can do this using a life-cycle method called componentDidMount. When we created our class components, we said the one and only required method we need is the random method. There are also some optional methods too, and one which we're going to now look at is called componentDidMount. As its name suggests, it will run any code we add after the component has been mounted to the DOM. A good example of one we can use this, it's going to be to load the sample data into our state. We are going to add this one in the app.js just below our state objects. Let's add the componentDidMount. This is method, so add the brackets and the curly braces. I often add my state at the top, followed by any life-cycle methods such as this, then any custom methods, and then followed by the render. This is completely optional and it's up to you how you'd like to lay these out. But this is just something I've gotten in habits of doing. ComponentDidMount needs to update the state so let's copy this line from before, paste our set state method inside here. We can also remove this update state method, save this file. If we now go off to the browser and refresh, we now see our state has been updated with the console.table without click on a button. There are other life-cycle methods available too, such as componentDidUpdates, which will run some code after a change has caused the component to update such as changing states. We also have components will amount to perform any actions we need to do after a component has been mounted from the DOM. These now leaves us with the three boards from our sample data. Set the states and typically what we would now want to do, is to loop through these and then display the data in the browser. Since our data is in an array format, we can use the JavaScript array method called Map. This is just regular JavaScript and nothing specific to react. If we go to the app.js, we can go down to the random method and we're going to replace all the contents with our map. Remove the three elements inside of our div wrapper. Then inside of here, since we're using JavaScript, we can use the curly braces. We can access state just like before, with the start of state. Remember, this is pointing to our component instance. So we can access state with this dot state and then the name of boards, but I did not call the dots mock method. Inside here we can pass in a variable name of board for each item it finds in the array, then create an arrow function. This is going to be responsible for display in each one of our boards, so let's add a div which is going to surround each one of the free boards in our sample data. Then we're going to output three elements. One for the ID, one for the title and then one for the background. First of all, let's create a span element, which is going to display the board ID. We can access each board with this board variable, then pass in the ID. Next stop, a level three heading which is going to display the board title again in the curly braces. Then third and finally, we can add a p element, which is going to display the board backgrounds. Now we can see this and then go over to our project in the browser. If we refresh we do see our free boards on the screen. We've got the garden ideas, we have the house ideas, and also the course ideas at the top with our board title, our ID, and the background color. However, inside of the browser we do see the console has an error message of each child in a list should have a unique key prop. When rendering out a list of items just like this, we need to also add a unique key for each elements. This helps React identify which items have been added, updated, or removed. Now we can use the board ID as a key, but later we'll use the Firebase unique ID for our items. Back to the app.js, we can go to the wrapper, which is this div. We can then add a key which is going to be equal to the board.ID. Then back on to the browser, I will now see our error message has now disappeared. These keys must be unique so if we had more than one board with the same key, this will cause an error in the console too. In the next video, we're going to replace these rendered outs elements with an actual component and discover how we can pass data using props.
10. Passing data as props: In the last video, we displayed each board item by leaping through and I'll put in the HTML elements. Now we are going to replace these three elements, which was the board ID, the board [inaudible] and the background color with a board components. If we go over to the app.js, we already have the board components imported at the top of the file. So now we can use this in side of the map method in place of all the existing code. Rather than this surround DIV, we can replace this. Then inside the map method, we're going to simply output the board. If I now save this and go over to the browser, there is quite a lot going on here. So we can clean up the board components to simplify things. So let's go to the board.js, currently I'll put in the title. Then two list components at your place is just with the title of board components. If we save this, things become a lot more clearer since we're now output in our three boards. One for each item in our sample data. In the app.js, just because we have this board components nested inside, this doesn't mean inherits all of the data which it needs. We have to pass any data to the board using props, props is a way we pass data to child components, i.e, props always get passed down the component tree. This is one of the golden rules of react. We've pass down data as a prop, with state we always lift it up, meaning if we had a state which is shared by two components, we always lift the state up to a parent component. So both components can then have access to it. We passed on props just like a HTML attributes and then give it a name and a value. So for example, we want to pass our props from this board information to this board components. We can add the attributes and we're going to set this prop name to the board. The data we want to pass is going to be in the curly braces and that this is going to be the board data from our map. Let's add board into here, give this a save. We can then access the board prop inside of the board components. So head over to the board.js. The way we access this is very similar to what we did with states rather than [inaudible] state inside the curly braces, we access the props with this top props. The name of the prop which you pass down was the board. So this top props to board. Then we have access to the board title, just like we did before in the last video. With the browser, we now see our three board titles, of course, house, and garden ideas. We can also pass props down more than one component level 2. We'll cover this very soon. Now I want to put this into practice a bit more by creating the homepage, which will display a board preview components. Take any look at the final project. This is what we are going to be creating. There will be a board preview components for each one of the boards on the screen. Then if we click on this, it will be taken to the full board view. Let's create this inside of a new component folder, open sidebar. We can organize the components by creating a Pages folder inside here. As in this Pages folder has no difference on our components. The only change we need to make is the file path when importing. Inside of this pages folder, I'm going to create our file, the view [inaudible] scene and call this home.js. Home is also a component too but since this is going to be a page view, I've added this to the Pages folder to keep things more organized. Now we can go ahead and create our components by importing react from 'react'. This is also going to be a class components, which is going to extend React.Components. The curly braces, this needs the render method, which is going to return sum JSX. All I'm going to add for now is a level 1 heading with a title of home. The final thing to do down at the bottom of the file is to also export this with the export defaults. The name of our class, which is Home. This home components. If we take a look at the finish view, is going to be wrapper for all of these board previews. It's then going to pass down the props for the board title and also the background color. So first we need to create the board preview components, which will be used for each one of these items. Let's create a new file in the sidebar. This is not in the pages, this is just straight in to the components. Now this is going to be the BoardPreview.js. This is also a class-based components. So let's import Reacts from 'react', creates our class. This one is called the BoardPreview. So extends React.components, pass in the render method. Then return our GIS X code, which for now is going to be a simple P elements of board preview. Then at the bottom, let's not forget to export default, our class name of board preview. Then once you're done, give this file a safe. So we now have a situation where we need to pass down our props down two levels. Our state is stored in the app.js. We'll then it's passes data down to the home components, which is this wrapper. Then from the home component down to each one of these ball previews. Luckily, this is not too difficult to do. The first step is to actually display the home components. If you go to the app.js, we can first import the home component which we created from our file path, which is./components. Remember this is also in the Pages folder and the name of home down in the return section of our render method. We can also replace all of this with the home components. As we check, this is displaying in our projects. So now we see the home components. The next step is the pass this home components, these state of boards, so we can do this via props. The board is going to be equal to this.state.boards. So this is our props now pass down one level. Let's go over to the home.js, where we can now access these props. The next stage is the pass down from his home components to the board preview. The first thing we need to do is to actually import the board preview. This just lives inside of the components folder. We can access this with dot dot slash and then ball preview. Down in the random effort, we could simply output the board preview. But remember we do have multiple boards. In our case, we have three starred into states. Therefore, we need to map through this data and then output a ball preview component for each one. Just like before, we use this top props, the boards. Since there is three of them, we're going to call the JavaScript map method. For each one, we're going to get a key which we use in just a moment. But first, let's output the board preview. Each item is stored inside of this key variable, which we can now use as a key and imposter each individual board as a prop. As we know from before, we also need to pass these key as an attribute and set this equal to our variable of key. Then we need to pass down the individual bond to this board preview that's at this on a separate lines so it's more readable. We can pass down the individual board and we can access is with this dot props, dot boards. This is accessing all the boards which we received via props. We can then pass in a key to get the individual board from the boards array. Remember that this key is each individual item. The first time we lived through the boards, it will then output a board components or a board preview, and then pass the individual board. It will then live through the second one, also outputs a second board preview and then also pass the second board as a prop. It will enter this for each item in our array. Now if we say this, we can now go to the board preview and make use of this board prop. The [inaudible] inside, let's return statements. We can remove the hard-coded board preview. We can then access this dot props, the board prop and then we can access the board title. Let's save this and refresh before we go any further and we'll see in the console we have an error. We have no unexpected token in the home dot js. Back over to the home. This is because in our returns section we are putting in two adjacent components. Slight remove this and surrounded in a div. But remember, reacts will only allow us to have one parent item as a rapper. At the end of the result section, we can close this off, reload. This now gives us a error message of "Cannot read property title of undefined." Why can we not read the title inside of our components? The board preview. This is this line of code just here. Well, the reason this is happening is because although all boards in these sample data are stored as an array, each individual board is stored as an object, so we have in-state an array of objects. If we go to the home components inside here we use.map method. Map is an array method. What we are trying to use it here on a board, objects. To fix these we can wrap this. props.boards which is an objects in the object.keys method. Let's cut this.props,.boards and then we can use objects.keys. Then inside of the brackets we can paste this back in. Object.keys is a object method which will pull out all of the object's property names and then return an array. Here we are basically converting this object data to being array. Therefore, we can use the.map method and everything you should now work as intended. This object.keys is a regular JavaScript method. Again, nothing specific to react. Now if we save this file and go back over to the browser, this error now goes away, good and things and are working correctly. We've passed the board state down two levels and then I'll put the title in the board preview. We now ask a stage where we have nested components. Uncommonly, all we can see is plain text in the browser. Without having a router in place, a switch between our pages or components. It can become hard to visualize exactly what is going on with our components. To help with this, we can use the React Developer Tools, which is available for Chrome and Firefox. If you have installed them early in the course when setting things up, great. If not, go ahead and search for the reactive tools and add the extension for Chrome or Firefox. Once this is done, you'll be able to right click and then inspect and now we should see the react developer tools available to select, so click on this. The React developer tools is something which we will use quite a lot for this course. We'll get lots more practice. We can see currently in the component tree, we have the main app wrapper. We can open this up and then inside we have a surrounding div which will contain our home components. This is exactly what we see in the app.js. We have our components, we have our div and then we have our home component nested inside, which is passing down the boards as props. We can also see the props inside the developer tools. If we click on the home components, we see we're passing down the boards as props, which is an array with three items. We can inspect this and see all the information for each item. We see that a lot, these boards are an array. These individual items are an object, which is why we needed to convert each item with object.keys. If we open up the home wrapper, we then see inside each of the board previews. They also have the key to allow to react to correctly update each list item. We can select these and we also see the props which are passed down. This is an object with the individual board where we can access the background, the ID and the title. It says title, which we've used to output the browser, as well as props. If you go to the main app components, we also see the state which is component holds and this is the information which you pull in from the sample data and then pass down via props. These developer tools are really useful and we'll make use of these as we go through the course. Next up, we're going to stick with the subjective props and take a look at how we can pass methods between components.
11. Passing methods as props: It's not just data we can pass down to components. We can also pass down a method two. The method we will be adding soon is to create a new board, which will obtain the board's state in the app.js. Now since we are updating the state stored in app.js, we also add. we create new board method inside here too. Let's go over and create is now in the app.js, I'll go to this file. Then it just under our component will mount. We can create a custom method called "createNewboard", this is going to be a ES6 arrow function, which is going to take in a board, which will pass to it soon. So here we're going to update the state a little bit differently. Let's take a look at how we're going to use this dot set state. Inside here, we're still going to pass in an object and update our boards. But this time we're going to create an array. So here when updating the state, when using React, we usually don't want to mutate the state directly. It is best first, take a copy of the existing state. We can do this with the spread operator, which is a three dots. We can take a copy of the existing states by using "this.state.boards". Then after this separated by a comma, we can merge in our new data, which is going to be this board variable, which you pass in through our method. So when we call this will pass the data about the new board, will then update the state, will then grab a copy of the existing states and then merge into it's our new board. If we take a look at the finished version just here, this is the home components. Inside here is where we're going to "Create a new board". Therefore, triggering this method. This method needs be triggered from the home components, meaning when it pass a reference to this method and how do we pass data down to child components? We do this via props. So in app.js, let's go down to where we render our home components. We can then pass a reference to our method. So, "Create new board". In fact, we can add this on switch online. Then we can set this equal to this. Then our method name called "createnewboard". Over in the home components, which is the home.js, we can create a button to create our new board. So inside of our "div", Let's create this now. Inside a here we can create a click handler. So "onClick", we're then going to create a new method called "this.newBoard" and its acts of newboard inside here. So this new board method, which we are calling here, has nothing to do with the one we've passed down by states. We'll call this in just a moment. Let's go up and create this now outside of the random method, we can now create this.So let's create our "newBoard". Setup, a ES6 arrow function. So inside here we want to do two things. First of all, we want to grab all of the board data from our form and then we're going to call the create new board method, which are passed down from app.js. At the moment, we don't have this form to grab his data. So I'm just going to have to code in some data for now. Let's create our board objects. so "const board" is going to be equal to a new object. This needs a title called this anything which you want. I want to say, "Trips to take this year", separated by a comma. We also need a background for this board. I'm going to set its "background" to be a string value," 80ffaa". Next up I'm going to add the "createdAt" property. This is going to be a "new Date". So a new script dates. We're going to be stored in the date for the new Board and also the new list and new cards. This will allow us later on to return all of this information back in order from when they were created. So this is our new board now hard-coded. We can then call the create new board method, which will be passed down via props and sent off this new bond as an argument. So just after our objects "this.props.createNewboard". Fastening this board which illustrated. So now this part we will pass with the createNewboard method. It will call it in the app.js. This method will then receive the board and then merge it into states. So let's save this and then go over to our project. We can try this out. Let's go to our app. We have the new ball button. Let's click on this. Then we get a incident update of trips to take this year. Greatest means we now have this new mode at a state. This is what we mentioned earlier when we said that each time the state is updated, React will then update all components which need that particular piece of information. We can also see in the app.js, if we go down to the state, we now have our extra board added inside here. This is one which produced hard-coded and then passed as arguments with this method. If we refresh though, this item will disappear since we don't have any permanent database just yet. But this is something which will add later in the course. Now let's move on to the list. If we look at this final board view and then click on any of the ball previews within it, taken it to the board components. This board component will need access to all the currently loaded lists. In our case, we just have these free. I would also need to add a new list input down at the bottom. Currently in our output don't see this ball view. If we go over all secretly loaded is the home components and then next inside our board previews. We can begin to work with this board components. We can go over to the app.js and add the temporarily. This will be until we introduce the routing in a later section. So first of all, in the app.js makes you we still have the board info from before. Then scroll down to our random method. We can also add the board components inside of our wrapper. So I'll close this now and go over to this board.js. We can add the lists in state. So each individual component can also have its own local states. Let's create our state objects. I want to load up the current list, and set this to an initial value of an empty array. I've called this state, the current lists because later on, we'll also filter the lists to only show the ones for a particular board. We can then grab our lists from the sample data. First of all, by importing at the top of the file. I'm going to import our data from the file path, which is dot dot slash sample data. But then once again, we can use componentDidMount to load these into state. This is a method we should call this dot setState. We'll set our objects, which is going to grab the current lists and set this equal to our sample data, which is data dot lists. Data being a variable which we have from our sample data, and then the list is the list data which you have just here. Now we have these current lists. What do we want to do with them? Well, we want to render out a list component for each one, just like the free which you see here. We do this just like earlier when we live through the data, and now put a list component for each one. Let's get started in the board.js. Let's go down to our random method and we can begin to work inside here. First of all, in the surrounding div, let's add a class name which is going to be equal to list-wrapper. This is for CSS. Notice here how we're using the class name rather than just class, as would do in regular HTML. Well, when using react, the class word is a reserved keyword. Therefore, when adding any CSS classes, we do need to use this class name attributes in its place. Inside here, we could move our title from four. Then inside of the curly braces, we're going to map through the current lists. So just like before, we're going to use this.state.current lists. Just like before, this.state.current lists is an object rather than an array. To solve this, I'm going to cut this out, and again, use objects.keys, and then inside the brackets we can paste this back in. Just like earlier, this will convert this to be an array, so we can use the dot map method. We'll also going to pass in the key, settled the arrow function. For each list in states, we're going to then run down the list components. This list also needs to take in a key. This key is going to be equal to this.state.current lists. We're not going to pass in the individual list with this key, and then grab the ID. Make sure we still have the list components imported at the top of the file from earlier. Give this file a save. Then we can go over to the browser and check this out. Now we'll see our components rendered to the screen. There's quite a lot going on here. Let's clean up the list components. Let's go into the list.js. Then rather than outputing our free cards, we're going remove this. It should look a lot more clear now, if we update this. That's our free list components. It is probably a little difficult to see what is happening here, so let's open up the react developed tools. Take a closer look. Starting at the top level, we have the app.js with our boards which are in state. Inside of here we have a surrounding div, which will then output the home components, displaying the cause, house and garden ideas. After this, we temporarily added in the board component. We could see this and the board components is rendering out free list items. Each list item is you simply opportune the text of list component, which is just here. We'll also soon output a list title and also the counts. With these lists now displaying on the board, we can do a similar thing to early in this video and also add a new list. Over in the board.js. We can do this by creating a new method. Just under component in mount. Let's create a new method called create new list. They serve as the arrow function. Inside here we're going to construct our new list. This is just going to be sampled data for now. We first need to add an ID to this list. Later on we're going to be using Firebase to grab this ID. But for now we can use math.dot random to generate a new ID using JavaScript. The title, let's call this my amazing list. This also needs to be linked to a board. We can choose a ID. Let's go for 300. We can also add the createdAt property ans set this to be a new date using JavaScripts. Now we have our new list created. The next thing to do is now to push this to our currently state. Now we can do this with this.state. Add in our objects. The state which we want to obtain is the current lists. Just like before, current list is an array so we can pass this in. We're, first of all, going to merge in the current lists, with the three dots. This.state.current lists separated by a comma. We then go to merge in to our current state. The list which was created, just above. This is all we need to do now for this method, the next step is to create a button to trigger this method follows. We do this down in the random method. Let's just go under the list wrapper. Let's create a button. We can add a on-click event handler, which is going to trigger our method, which is called this.create new lists. Then a name of new list for our button. Once this is done, give this file save and we can go over to the browser. Let's try clicking on our new list button. Then we'll get a new list component rendered as green. If we go into our app and then into our board. Inside here, we can check out the current state for all board. We now have our four list items. If we go to our last one, which is one which you just added, we see the title of my amazing list. First, again, just like before, if we reload the browser, this will disappear. Since you don't currently have any permanent storage. To round things off, rather than outputting the text of list components, we can access the prompts as to it instead. First of all, in the board.js. We can pass down these props to each list. We already have the key. That's fine. Then after this, we can also pass our list. We can grab the data with this.state. Our current lists, passing in the key, save this file, and then we can modify our list components so I'll put the title of the list.js. First of all, let's add a class name to the wrapper. The class name is going to be equal to list or our CSS. This title is going to also be in a surrounding div, which is going to have a class name of list header. Then close this off. We can now move our p elements inside of this header section, and replace the text of least components with our props. Inside the curly braces, this top props.list, and then we can access the list title. If all is working well, we should now go over to the browser and now see the title of our free lists. We can also click on new list, and we'll see the title for this one too. Good. If everything is working now for you, we're going to now move on to the next video. We're going to look up prop type validation.
12. Prop type validation: when passing around data between components, it is a good idea to provide some validation. Jacquet component is getting exactly the data which it needs. For example, if a component expects an object but gets an array, it could break our up. And this is exactly what we've seen before, when we needed to convert an object using object darkies. This will be using proper types, which is a library provided by Facebook to perform these checks. It is simple to get open running words improvises with errors during development. The owners. If our prototype fails, let's install this over in the terminal. We can close down or terminal with command or control, see no money to install this from MPM with the MP M I, and then the package name, which is prop types. It's answer and give us a few moments to install inside of your project and then come back once this is done. Okay, welcome back. Once this is installed, we need to import it into each file which receives the props. Let's begin at the top of the tree, which is the upto Js. This is the very top level, so it doesn't receive any prompts from of components. But instead he does pass props down to the home and also the boards later on. In the course the home components receives the boards on the type of the boards is in Ray and also create new board is a function. So let's begin over in this home component. How could begin a work problem? Validation. First of all, at the top of the file, we can import the package prototypes. Comfortable. P Auntie could impart this from the proper times module. Okay, so next I'm going to set up these prop types right out of the bottom. The file. I want to do this just above our export defaults. We can do this with the name of all components, which is home. Never gone. Set the proper types. So little case P. In this case, on immigrants, that is equal to an object which will contain the prototype for each proper, which is passed down. The 1st 1 is for the boards. Then we can set to the proper types, which is capital P anti, which is the one we imported up at the top. And then after this concert, what type of data we expect to receive if we time thought. We can see some of these suggestions inside here when we want. In this case is an array. You can also set this to be a required field which is required separated by a comma. We can also do the same for our second prop, which is create new board. Great new ball This time is a function and we can declare we want a type of function with bunk. This is also required. So also changes on to the end. The next thing to do is to restart our server with MPM stars. Once this is done looking out testes, aisles over in the browser, we don't see any problems at the moment. But if we change one of the proper types, let's say from array to be a type of object. Let's say this. I mean, I'll see a failed prop type that so called back and changes to be an array once more under , Then save this final. Let's go into the sidebar. The next one down is the board dot Js board dot Js is not currently receiving a props has moved down to the ball preview. We will come back to this board later on in the course, just like before. The first thing to do is to import the proper types and then, after this week in once more, go right down to the very bottom, just above our export default, the component name, off board preview and then set the proper time with a lower case, be as that it's up to be equal to object. The one and only proper that the ball preview is can is from home. And if we go up when we're internally board preview was sending the board prop. This is a type of object. Let's set up the prop types Capital P and A Capital T. This is a type of objects on that. This is also required to the next components down in the sidebar is going to be the card. Let's click on this. We will come back to this soon, since we're not using this card components just yet in our project. So finally we have the list doctor s components. This takes in a list, so also needs a proper type. Let's do our imports about the top in full prototypes from prop types scroll down. We can set these up at the bottom with less door prop types, so I will object up the single prop type. Which receiving is the list the prototype is an object on. This is also required to We will, of course, on today's. As we passed more props on also create more components, they can't doctors. Component we mentioned for is not currently in use, but we're going to make use of this now by including it for each card in our sample data. As we see here, the card component is nested inside off each list, meaning when it's on this over in the list. Doctor, as components, let's head over to the list. Dr A s arm. We can do this now. So inside here it's goes down the side ball. We're going to rent out a car components for each card in a list. Remember the sample data as a cards array on one card, a rate per list. So let's go through the list and we can do this now by my pin through all props underneath the title. On Underneath the list. Harder. Let's open up the curly braces this time is a object. So we also need to run object jockeys to transform our props into an array. The props once transform. Is this not props? The list Note cards. What? I'm going to mop through the results. Each item will be giving this key variable name. And then inside of these rockets, we cannot put one card per item found in the loop. And make sure this has to close and rockets, and then inside here, we can all put over card components, make you this is still imported about the top of the file, which is we cannot a key, but you're going to be equal to all key. Valuable. We can pass the data as props. This is going to be this. No props. Don't list dot com and then inside the square brackets would pass in the key. Close this off with a forward slash on the factors on this onto its online. There we go. Okay, so now we're rendering out a card on passing the props. Let's head over to the card, Doctor. Yes, We can all handle this data passed to it. At the moment, we just have a div which is going to rent out the text. So first things first we could go up to the top on import our prototypes and from the proper times package. Then at these right at the very bottom above our export default. The component name of cards. No prob times set up a object. The proper name is data on the prop type is an object, which is also required. So before we go any further, let's say this card components and then go over to the browser and we have a never in the list line 15. Let's go there now line 15. We have the data. This top prop start list. Andi should be cards within s on the end. Let's try this now. Good. So now let's see a list title and also the cards assigned to each one. It is a little difficult to see what's going on. No, because the styling is missing, you know, components. So we have bean, adding, it's, um, classes as we go along. Such as The list had a on also this list, and they have also provided some CSS to go with his course to make up look a bit better. You can find this CSS file as they download with the course. So go ahead and grab the CSS as a down lord. And then once you don't know, we can paste this inside of the app dot CSS. So I'm going to remove all of the existing styles and then paste in all styles which have been provided. So now if we give this final save and go off to the browser So now we can see more clearly our free list in the sample data, we have our list titles and then we have two cards inside of each list. So there is still a bit of work to do but can now see the list in cars more clearly. So this is it now for our prop types. I'm all answer this as we go for the rest of the course.
13. Controlled components: If we had over two any URL numbers such as 1,2,3 and then forward slash boards. This view is rendered out by the home components. This contains a new board button. If we click, this will then add some hard coded data to our board states. This new board button is wide up over in the home.js. This is a button and it will trigger a method called newboard. All this board data is currently hard-coded, but we want the user to add the board name and also to select the color. Just as with any of the websites, we can do this with a form. Let's have this over in the sidebar. We're going to go into the components and then create a new file for this called CreateBoardForm. With the dot js extension at the end and make sure you just spell right. There we go. The first thing we want to do is to import React from "react", just as we always do. Then it's going to be a class-based components. Want to call this the same as the file, which is CreateBoardForm. This is going to extends React components. Inside here we add our required random method, which is then going to simply return some js x as our AP elements. With the texts of hi. We'll come back to this in just a moment and create our reform. First, let's export default. CreateBoardForm. Save this file and then we can import this file in it to our home components. Scroll up to the top underneath our prop types. We can import CreateBoardForm. The file path we need is going to be dot dot slash. Then it says CreateBoardForm. Scrolling down to our random effort, we no longer need this button which will have here, since we are going to replace this with a form. In the place here we can add our CreateBoardForm components. Closes off while we're here till we can add a board-preview wrapper, which is going to be a surrounding dive. This will just add the style in which we need using CSS. We can add our class name. This one is going to be equal to board-preview-wrapper. Then grab the closing dive and add this just after the closing curly brace. This board-preview-wrapper will give us the CSS grid layout for all of our board-previews. Save this file and then go over to the browser and now we see the text of hi, which means our component is now being rendered. Also our free board-previews and are being displayed in the grid format rather than in a list. Back over to the CreateBoardForm components. We can create our form markup. Let's head over. In place of this high text, we can remove this. We can add a form inside here. This form is also going to have a className, which becomes or create-board-wrapper. First of all, we need a input with the type of text. Which is going to be for our board name. Close this off and on a separate line i'm going to add the type which is going to be equal to text. It's also needs the name, which is going to be equal to name. Then finally a placeholder value, which is going to be board name. The second input which is formed is going to need is going to be a select box. This is how the user can select the background color for this board. Creates a select box. Let's open and close this. This disliked also needs a name attributes which is going to be equal to background. Inside here will then list our options which are available for the user. I'm going to add six different colors. You can add any color value which you like these, or you can stick with ones which I want to choose. The first one is going to be a blue value. We can add the same using the value attributes. The x value of 80ccff. Want to copy and paste this in five more times. Giving us six option values. Is a common is going to be for a green color. The x value is going to be 80ffaa. The third one is going to be red, which is a value of f94a1e. The fourth one is for a pink color. The x value this time is ffb3ff. Then we have a purple second-to-last, which is bf00ff. Finally we have the orange color. This is ffad, double three, and there's our six colors. The last item we need to add is for a submit button with the texts of creating new board. It's also needs a type which is going to be submit. This is all we need to do for our form. Save this file and then go over to the browser and open the top. We now see our inputs of board name. We have our dropdown with these lactic colors and our submit button. This is our form now displayed in the browser. But now we need a way to get the data input by the user. There are a couple of ways of doing this when using React. First is what we're going to look at now called a controlled components. This generally means React takes control of the data, which we type in and then stores it into states. HTML form inputs such as this input and select we have typically maintain their own state, meaning the unaware of what the user typed in. You may have used the event.target.value before to accesses this. We can then access this value and place it into state. Once it is then in state, we can use it to create our new board. We can begin by creating our default state. Let's go over to CreateBoardForm. Just underneath our class title. Let's add our state objects. First of all, we can add the title and satisfy an initial value of an empty string. We can also set a default background based string value of 80ccff, which is just our first blue value. This will be our default background color if none over is selected. Scroll down into a form. Inside of these inputs, we can create an inline event handler, set the state when a user types into the inputs. We can do this just under the placeholder. We can add the on change event handler and satisfy a inline function, which takes in the event data as e. This is going to run a function which is going to run states. We can pass this in as an object and the state which we want to change is the title which you want to set to e.targets. The value e.target. value is the event data which is typed in by the user. Then we can also do the same for the background too. Scroll down to our select just after the background inside the opening select tag. We can also add an on change event handler. At this again, in line passing in the event data, create our arrow function, which is also going to set state, with this dot set state, personal objects. But this time we want to set the background inside the states. This is also e for target of value. Each time the user types anything into the form or changes the select inputs, it will then run this function and update our state. Next, we can test this out by adding a on submit method to the form. Go down to our button and in fact, we'll add this to the actual form elements and these onto the online. This time the event handler is on submit. Once the form has been submitted, we then want to run a custom method called this a handle submit. This will cause the handle submit method to run each time the form has been submitted. We can test this out above with a simple console log. Outside our random method, we can create our custom method of handle submits passing in the event data. The first thing to do is to run e or prevent default. This will prevent the default behavior once the form has been submitted, which will then be to reload the browser, and we don't want to do this since one react to be in control of when the page reloads and updates. We can then do a simple console log to the browser, which is going to output this dot state. This dot state will then show us the title and background which the user has typed in once this form has been submitted. Let's say this and then go over to the browser. Into the console tab. Let's type anything into here. Change the value and create new board. This looks like we had a summit this, let's check what's going on. It's a spelling mistake, so handle, submit and let's try once more. Reload and we can add our test. Let's try with the default color. I'm going to have a title and a background. Let's change the color and also the title and there we go. Now the state has been updated with the value input by the user. Now we can finish off our method by creating our board. Install this as an object. Let's remove the console log. Create a constant for board. This will be an object which is going to take in the title, which we can grab from states with this dot state dot title, separated by comma. This also needs to grab the background. This is an easy one too. This is the start state, the background. Then we can add the value of created at, which just like we looked at earlier, is going to be equal to new dot date. Therefore, we can grab this from the database in time order. We don't have any user data just yet, so we can add a simple string. Let's go for a, b, c 1, 2 ,3 giving us the board data which we need to send off to the database. If we go over to the app.js, we still have a method called create new board. This also takes in the boards, but we have this now which we can pass along with the method. We do need to pass this method down as a prop and we'll get to this in just a moment. But first we want to add an if statement to first check if the board dot title exists. We want to check if this board dot title is there, because if it's not, this means that the user is trying to submit a board without a name. We also want to check if the board dot background exists too, which it should, because we have this stored into state. We can then run our create new board method with this dot prop, dot create a new board. Passing in our new board objects. Now the next step is to actually make sure that these props are being received by this form. Open the app.js, we have our create new board method, which is set in the states. We're currently putting this down into the home components. Let's head over to the home dot js, this home dot js then it needs to passes this down to create board form. We can do this now, so creates new board. This is equal to our props, so this dot props dot create new board. This should now be available in our form. Just one thing to do before we go ahead and check this out is we still have this new broad method just above in our home components. We can now remove this since this is no longer needed. Save this and make sure all of our files are saved and head over to the browser. We can now test this out. Let's add a new board. I'm going to go forward to do, which is going to be a red color and then create new board. Create new board is not a function. This is over in here. Lowercase w, let's try one more. That's due in a color of red. Create new boards and now we'll see our board has been pushed to states and then rendered in the browser. To round off this video, we are passing props, so we needs some property validation inside of all form. Let's first begin in the create board form by importing our prop types from our prop types package. Then as ever, we can add this down at the bottom of our components, just above our export. Creates board form dot prop types, lowercase p, set of all objects. The single prop which we are receiving for this component is create new board. This new board is going to have the prop type of function, which will add with dot func. This is also required since we always want to be able to add a new board. Let's save this and go over to the browser and check there's no issues, and everything looks fine. The next topic we'll continue looking at forms by taking a look at on control components and also using refs.
14. Uncontrolled components and refs: The controlled method we looked at in the last video, is the generally preferred way to handle forms. Since react is in full control and can also handle any updates. Now we will discover an alternative way of creating a form in react, and this is called an uncontrolled component. This way, the form data is handled by the DOM and it can be a useful alternative to avoid writing event handlers for every form inputs. For this example, we will build in the forms and a new list. We do this over in the board.js components, and on this slide here, this is the new list inputs we see at the bottom left, so looking at this at the bottom of the bowl components after the list wrapper div. Let's head over there now into our project in Visual Studio Code. Let's open up the board.js, and then if we go to the closing div for this list wrapper which is this one here. We can then create our form. Inside this form, we're going to add a submit event handler. On Submit isn't going to fire off a custom method, which is called the star, creates a new list. If we scroll up to the top of these components, we already have create new lists inside of our methods, so we can make use of this very soon. After this, we can also add a class name for our styling and set this to new list wrapper. Now after the former gone to nest inside a form input, the input is going to have the type of text it self closes. On new line we can add the type of text. Since all we receive in by the user is the text inputs for a new list, we also need a name. We can simply call his name, and then a placeholder value to let the user know exactly what's typing and add a plus symbol and then the text off new list. Here, currently we have our surrounded div, followed by a form element just afterwards. As we already know, react won't let us do this because it needs a parent's elements. That's add a div as a wrapper. Let's cross out the closing tag and places just after our form. Let's save this, and then over to the browser. Inside the browser we have our new list on inputs, and also this button which we have from earlier, which is triggering the same method. Let's go down into our random method. We can remove this button from earlier since we now have our form input. Then scroll up to our create new list method, which will set the state. Since in this version we're not using state to manage the form inputs, we need a way to access the DOM elements and then set them to this list object, ie we need to grab the input which the user has entered and set this to our list object, and react gives us a way to do this using refs. Refs are ways access to the DOM and they give us all the information we need, including the value entered into a form input. We can create a new ref with the create ref method. Let's do this above create new lists. We give our ref name, I want to call mine addboardinputs. To keep the descriptive name can set a ref with react.create ref, and the brackets used afterwards. We can then pass it to our inputs as a ref attributes. Let's call onboard inputs, go down to the elements which you want the information from. I'm going to add this anywhere as an attribute. We can set the ref equal to these dots add board input. This will attach this reference to this HTML input, and we can access it above in our method to drop the properties which we need up in it creates a new list. We can also now pass in the event info with the e variable, then we can access this to prevent the default behavior. This will basically stop the page from reloading when we submit the form. To test this, I'm going to comment out the code and then console log the ref. Let's remove the set states and also our list, and assume a console log with the value of our ref, which is this,.addBoardInputs. We don't need the semicolon, so let's go to the browser. We have an arrow inside of the board, so we got the brand new list, uncomment out this closing brace, and there we go. Now inside of our new list, without anything inside here, go to the console, and then we get the value of our ref, which points to our current input. Now is a lot of information about the input just here. But the one we're particularly interested in is the current value, so up in our console log, we can now release down to.current.value. This will give us the value entered by the user, let's type anything into this input. We now get the text which has been entered by the user. Back over to our ball, we can now uncomment out this code. That's like all the lines when commented out, which is the list, all the way down to set state. We can also remove the console log, and now we can use the ref value inside our title instead of this hard-coded value. We can do this by removing the string, and then instead we can point to this.addBoardInputs, and then just as we've seen before in the console log, we can grab the current value. Now save this and let's go over to the browser. Let's try anything inside here, new list two, and now again error. The reason for this is over in the list components. Inside here we're looping through any available cards inside of our list. However, inside of this ball components, when we create a new list, we have no card's setup inside this object. Therefore, react cannot find any values and causes an error. Later on if I based these cars will separate from the lists, so as a temporary measure, I'm going to add some simple cards when creating a new list. Just after new days we'll temporarily add in some cards which is going to be an array of objects. Let's add id 1, some text and say card 1. Separate by common, we can add a second object with an id of 2 and also some text of card 2, and also add the comma just after created at. Let's go to the browser, and now if we add a new list, it answers. The new list is now added inside the browser. Just before we wrap this up, there is a few small issues to fix. First of all, if we delete the contents from our form inputs and hit enter, we see we can now add an empty list, and also number 2 the input doesn't clear after we add a new list. Hit enter, and we want this value to be then cleared for the next list. These are pretty simple things to fix. First, we can add a if statement to check if the title is present, before we set a state. We can do this in side of the board.js. Let's look for our set fake call, which is just here. On the line above we can create an if statement to check if the list.title is present. If this.set state and then move this inside, this will enter, stop an empty list being added. We can test this. If we hit enter on this new list, we see that no new list has been added. Next one is clear the input after we submit a new list, we can do this over inside of the board,.js. Just after this stage, we can refresh or reset the value of our ref so these dots are board input. We can set the column value, just like we used before to be equal to an empty string. Test this out. Anything inside here. And now our new list inputs is now empty. Now this is working, we can get a little bit more practice in the next video by creating the new card form.
15. Create new card form: The formed out new card is going to be similar to the last video, so we'll get a little bit more practice using graphs and also pushing to all states object. This will be the new card inputs we see at the bottom of each of these three lists, minimum connected in the least components on this cards. Let's head over to the list.js. Inside of the list components and underneath our current section, we can also add a new form, so just under our loop and also still within this surrounding div, we can then add a form. The form is going to have a on submit method, which is going to be equal to the value of this.createNewCard. We can also add a class name and set this to new-card-wrapper. Also add this to the on-line, so it's more clear. Now inside of this form, we can go ahead and add our one and our input, just like we did when adding a new list. The input is going to have the type of text. Let's close this off, and on a new line we can add the type. After this, this is also going to have the name and this is equal to name, and then finally a placeholder, which just like the last video is going to be a plus symbol, and then the text of new card. This is all we need to do for our form. This will also need a ref too, so we can create this at the top of our class. Just above our random effort we can add our nameInput, answer this to React.createRef. We then need to grab this nameInput and add this to our form. Inside the input as an attribute we can add the ref, just like we've used before, and so it's to the value of this.nameInput , linking the value of this input to our ref. At the moment for simplicity our cards are contained inside of the lists in the sample data. Soon all the boards, lists and also the cards will also be independence, and then we link these via IDs. We can begin this process by adding the current card states inside the E2. Up at the top of these components, we can create our state object, and this state is going to be responsible for storing the current cards. At the moment though, this is the initial state which is going to be set to an empty array, and the process of creating a new card is very similar to the last video when we added a new list. All we need to do is go below our ref outside of our random effort and then we can create a new card, and remember this name most link up with the method which we are added on submit, so "create new card" is going to be a function which is going to take in the event info. We'll set up our arrow function just like this. We can then prevent the default behavior to stop the browser from reloading, then creates our card. We can store this card inside of a constant and save this to an object. The card object is going to have the text, the list ID which is linked to, an array of labels, and also the date which it was created out. First of all, the text which is for this card we can grab from our refs. This is stored inside of nameInput, and once again we can grab the value with.currrent.value. Separated with the comma, we can also link this to a list by adding a listId. Later on in this course, this listId will be automatically placed in follows, but for now we can add any value inside here. Next to up a card will also need an array of labels, so let's set this to an initial empty array, and also the createdAt, which is going to be equal to a new JavaScript date. Below this object, we can also set the states, but just before we do this we'll check if the card.text is present, which will stop any form inputs from being submitted, which has no value. We can then call this.setState, as in our objects. These states which we want to set is the colored cards, so we're going to do what we've done previously. Inside this state object we're going to set the currentCards by imagining the currentState with the spread operator, so this.state.currentCards, then separated by comma will also add in our new card. The next thing to do after this is to also reset our form input, so let's just add this onto a new line so it's more clear. Then below this curly brace for the if statements we can then reset the text input box by accessing the ref with nameInput, and then set the current.value to be equal to an empty string. To check if this is working, we can do a quick console log just after this with the string of new card added, and we can add onto the end the card.text or to the browser. We now have our new card form inputs at the end of each list, so let's add anything onto here. Let me get new card added and then text. Let's try this one, and now these are all working fine. I'm going to leave the cards as they are for now, since we'll begin the real card data from [inaudible] base in a later section, and then linking these cards to each list.
16. Setting up React router: At the moment in our project, we've shown both the home and the board components. We can see this if we go to the React developer tools inside of our app, we have this home section, look at the top here and then below it we are rendering the board components. This is because we currently have no way of switching between these. Ideally, though, what we want after logging in is to be taken to this home components, where we can then select any of these boards, we can click on it and then be taken to this board view. Basically, that needs to be on different pages. To make this happen, we can install a router which will allow us to show certain components on certain URLs. For example, the URL of forward slash boards will render out this board components. I will also have a URL for home. Unfortunately, that react has no official router package but probably the most commonly used is the react-router-dom package, which is the web version of the router. This is a mature package which is actively maintained and we can install this using NPM. On to our project, let's open up a new terminal and then inside here, we're going to run NPM. I react-router-dom, separated by hyphens, let set this off. There is different approaches we can take to set up our router in the project, such as adding the router to a separate file and then importing it into our main app. We can also add it to our index.js. But since we only have a few pages to switch between, I'm going to set this up in our app.js. Let's head over there now and then up at the top, the first thing we need to do is to import the packages which we need from the browser router. These are named export, so we add these inside the curly braces. The first we need is the BrowserRouter, capital B, and then capital R separated by a comma. We also need to import the route package. Then third and finally, the switch is going to be imported from the router package, which is react-router-dom. First of all, we have this BrowserRouter. This is our actual router implementation. We will use it as a wrapper for all of our routes and uses the HTML5 history API. After this, we have the routes, this will be used to render a component for a given URL. Finally, we have switch, this is a wrapper for multiple routes. I will only ever render the first route which matches. Let's give this a go and add this to the random method by wrapping the components with the router. Down to our random method, where I will put our home on board, surrounding these two components inside the div. Then I want to make use of the BrowserRouter, which we just imported, so the opening tag, and then add the closing tag just after the board. We can then come and find our board and our home components and then make use of the router to control this. I'm going to begin with the board route. The home route takes the props so we'll come back to this very soon. Let's make use of our Routing part with a capital R, this is self-closing. Then inside we pass in the path which is going to be equal to forward slash board, so each time the user visits these routes of forward slash board, but then want to render out a component, we can add the components, and this one is going to be the board components, and this needs a capital B, to match the components which we imported at the top of this file. Back onto our router, another route which we need is a PageNotFound to catch all of your route which we don't add inside here. Just underneath our board, let's add a second route. We don't need to add a path this time because this will pick up all of the paths which are not declared above. Instead, all we need to do is to render out a component. I'm going to add a component called Page Not Found, then close this off. This component has not yet been created, so we can go ahead and do this now inside of components and rampages, let's add a new file. This is the PageNotFound.js. It's function will be pretty simple. I'm going to import React from here and then set this up as a function based component called PageNotFound because of the function, then inside here we're going to add a div. This div is simply going to render out a level three heading with the text of PageNotFound. Now we need to export this function down at the very bottom with a export default, the component name of PageNotFound. This will now allow us to import this in the app.js, so up at the top, we can import PageNotFound from the file path, which is dot slash components. This is also in the Pages folder and then the name of PageNotFound. Let's give this a save now and go to the browser, I have a error, BrowserRouter, so down on line 23, just add an R inside of that. Then alter the browser, so currently we're on the routes of 123 slash forwards. Now we'll get the PageNotFound, since this doesn't match any of the routes inside here. If we now try forward slash board, we should now see this board component rendered out to change our URL to be forward slash board. Now I see the board rendered out inside the browser, good. Just before we wrap up this video, I want to show you something which may catch you out when first using the browser router. If we go back over to the app.js. First of all, if we comment out the PageNotFound, and then we add one more route just above here. Those off, and then we can add a path which is going to be for the whole route of forward slash, so inside here you can render out any component. Let's simply go for the PageNotFound. If we save this file now and go over to the browser and then navigate to forward slash board, we see both the boards is rendered out and also the PageNotFound components, even though we're matching a URL of forward slash board. This may look a little strange because currently on the forward slash board routes, we will not want to render out the components of board. The reason this is happening is because technically, the home forward slash is also a match here too. If we look at forward slash board, this also begins with a forward slash, so we'll have a partial match at the beginning of the URL. This is enough to render the home component two and if we don't want this type of behavior, we can also add exact to the route, which will avoid this. Inside of our route we can add exact. Save this, and now on forward slash board, we only see the board component since using exact will not allow any partial matches, so I'm just going to reinstate our app, I uncomment out on PageNotFound. But this is something to watch out for when using the router. Next, we're going to move on to looking at how we can reintroduce the home components and also how we can pass down props using the router.
17. Passing props to a router component: This app.js file used to render out our home component and also the board. In the last video, when we switched to the router, we only rendered out the board component, leaving this home component until this video. This is because this home component also makes use of props, we pass down the boards, and also the create new board method. Now, when passing props using the router, the first instinct would be maybe to do something like this. If we had our home routes, we could pass in a component of home. We could then also pass down the props, just like we have commented out below, such as the boards. Let's add this is over and also create new board. Leave no component to mirror what we had earlier. However, though, if we were to save this and then go over to our app, we need to go over to the forward slash, which is the home component. We now see we get a error message in the console and also in the browser. We are receiving these errors because the home component is not receiving the props which it needs. Therefore, React is receiving this undefined or null value. When using the React router, we cannot pass down props in the traditional way. The solution is to pass in a render prop in the place of our component. Let's start by removing our props and also this home component. Then in place, we can add in a render prop. Inside here this takes in a function. So passing a arrow function, just like this. In here, we can then add our home component with our props. So just like we have earlier, down here we have the home component, which one is out our two boards. We can, in fact, copy this section and then add this inside of this function. In fact, we just need a home and not this board, so let's remove this. So first of all, let's save this file and check this out. We now see the home component rendering out the board previews, so this now removes our error. We also see this page not found component. Since it doesn't have a path, it will always render with our current router layout. To fix this, we can surround our routes with a switch statement. So inside the browser router we can make use of this switch package which we imported earlier. Just after browse router, we can pass this in. It has an opening and a closing tag, which sits just inside of our browser router. What switch will do is to look at our components and then only render the first one which matches. So if a forward slash or a forward slash board is found, the corresponding component will be rendered just like when using a regular JavaScript switch statements. If none are match, we are then left with the page not found down at the bottom. Let's save this and check that the page not found component is removed. Now, we'll just have the home components as expected. This now leaves us with the behavior which we would expect and this is how we can pass down props using the React router. Next, we're going to continue looking at this router and how we can pass parameters via the URL.
18. URL parameters: Using React router we can also pass parameters via the URL to over pages. Parameters are a section of the URL which can change. For example, if we had a user which is logged in and either use ID such as user one, we could then add "/boards". Would display all boards for user one. This user one section is dynamic, meaning it will change depending on which user is logged in. Also the same if we were to have various boards. We could also have a board. Then forward slash with the board ID to just 100, meaning that the 100 section would be dynamic, stored inside a variable and then available for use with React router. Let's go to our App.js and see how we can implement this. At the moment we have the forward slash, which is rendering out our "home" components. Later on in this course, this forward slash route will be used to render a login component. A user needs to login before seeing their own boards. Therefore, this now means this home component, which displays the user's boards, will need to be at a route such as this, so user one. Then we can see the available boards for that logged in user. Now it's not practical to add a different route, with a different path, for every user which is logged in in our website. Instead what we can do is add a colon, to add a dynamic section, followed by a name which we want to add to this variable. Let's call it the user ID. Now if we go over to the browser and we're to have "123/boards". This would now rend out to the home component and then store the value of 123 inside of this user ID. Because this section is dynamic, it will still render out these "Home" components regardless of what value is placed inside here. If we open up the "React developer tools". Let's click on this tab and then search for the "Home components" which we are currently viewing. Will just see the props over on the right-hand side with the "Boards" and also the "Create New board" function. There is currently no reference to this user ID. To say this, we need to pass down the router's data as a prop two. We could do this inside of the "Render prop." Inside here, we're going to pass in the props as variable to the function. Then inside of our "Home components", as are these were a separate line. We can also spread in the "Props." This will then merge in the router's data with the rest of the props, which you pass to the "Home components." Back over to the "Dev tools" Let's "Reload" go into "React" and search for the "Home components". Select this. Now alongside the "Boards" and "Create New board" we have three new props. This is the "History, location and match" props, which is all passed from the React router. We will look at these in more detail as we go through the rest of the course. But for now we can find the parameters or these URL parameters, inside of the props on the "Match" And then down to "Params" We therefore have this user ID variable with the value of 4-5-6, which is grabbed from this section here. Later we'll use this user ID to fetch the boards for the currently logged in user. But for now we can simply output the user in the "Home.js" file. Let's head over to the "Home." and just above our "Create Board Form," I'm going to output a "Span." And to display the user ID, we'll do this just as we would with any other props. We can access this "topprops.match" Which is these props, which you have just here. We need "match.paramas," and then the user ID. Let's give this a save and then go over to the browser. We now have the variable of 4-5-6. Let's try a different value inside here, so user one. Now this params is displayed inside the browser. We can also do this for our boards. If we go back to our "App.js" and then scroll down to our "Board components" We can now add in the board ID. Forward slash, this is a dynamic sections so we need z colon, the board ID. This will now allow us to go into the URL. Then at the "Board", and then "/boardID" just as one. Wherever dynamic data we pass in for the board ID will still run out this board components. Then the board ID will be stored inside of this variable. Since we also need pass down the router's props in its component tool, we can replace the component with the render function. Let's add these onto the online. We can remove the "components" and then replace this with the "render." This takes in a function which we're going to pass in the router's props. Inside here we then rend out our "Board components" on a separate line, but can also spread in the "props", which are the ones provided by the router, and then close off our board components. Let's test this is working over in the browser. To have forward slash one. Let's try 5,000. For each number which you pass in, we still see the "Board component" rendered to the screen. Let's search inside of the "Dev tools" for the board. We still have the props of "history, location" and "march" we grab the "paramas" inside here. With this now working we've taken another step towards structure which we need for the final project. Couldn't though we're just typing in these URLs. But in the next video, we will look at how we can navigate to these routes. When a user clicks on a "board" preview. And also how we can access the React router features when it's not possible to pass down props.
19. Using withRouter and push: Rather than typing in our dynamic URLs, which we done in the last video, we instead need a way to push them via our app. If we go over to our project in local host and then search for 1, 2, 3, both flash bonds. We have our free bonds here from the sample data. It would be good to be able to click on any of these and then be taken to the board components with the board ID as part of the URL. To do this, we can use the react router, to navigate to a particular URL and we can do this using the push method. While we are on this page, we can go to the reactive tools and open up the history object inside of the home components. Let's go down to the history inside the props. If we open this up. Inside here is where this push method is located. This push method will add a new entry onto the browser's history stock meaning you can use the browser's back and forth, Watson, and then his page will be stored into history. These free bonds, of course, house and garden ideas are located inside of the board preview components. This will leave us with a small issue. If we go to the DevTools and search for the board preview. If we select any of these board previews, the only props which you have is the actual board. We don't have access to the history object where push is located. You may think here we can just pass down the props like we did with the other components, and the answer is no or not directly. This board preview is a child of the home components. Therefore, it's not directly rendered by the router. Inside of the app.js, the only components which are child components of a router is this home components and also the board. The way around this is to use a package called the router. The router is a higher order components which will wrap our board preview. Therefore, passing the same much location and history props, and the router is also available in this same react router package which you already have installed. Let's go over to the board preview and we can import this at the top of the file. This is a named Export. Sony, to use the curly braces. We have router. This is from the same package, which is react-router dom. Then we can replace the contents inside of the random effort. Rather than just outputs in this.props.board.title. But I'm going to display a unordered list, and then each item inside here is going to be a list item. Each item is the board, so therefore we can then output this.prompts.board.title. Let's save this and take a look at the home components. We still have our free balls display in here. Let's add a little bit of styling inside of our unordered list. First of all, we can add a class name to trigger the CSS. This is board preview item. On the next line we're going to add a onclick event handler, which is going to trigger a method called goToBoard. Next up we're going to add a inline style, which is going to set the background color of each one is board previews. This will reflect the background-color, which we set when we create a new board. We can do this with a inline CSS property called background-color. Since this is JavaScript, we need to use the color case background-color rather than using the dash and lowercase values as we would with a regular CSS. We're going to set its background color equal to this.props.board.background. Now above this we can create our goToBoard method outside of the random method. Lets go just after our board preview class, we can create goToBoard, setup our function. First of all, we're going to grab the board ID, which we currently have insider props. If we go to the ball preview. Inside of the DevTools, inside the props, you have all board information which we need. First Iet's scrab probably bought ID installed this in sideway constant. Board ID is going to be equal to this.props.board.id. The second pass todays is then use the react router push method to centers to a different URL. What want to do is click on any of these links. Then we want to be taken to a new URL. So board, and then forward /theboardid, which we have stored inside of this variable. Let's do this now. This.props.history. Access the push method. This is going to take in an object where we can specify the path name. Since this pathname we'll use this board id variable. We need to use the back ticks to construct this. First of all, we can navigate to forward slashboard and then forward slash. We can use the template syntax of the Italo symbol curly braces, and then pass in the board ID. If we now say this file and then go over to our home components. We now have the free list items for our boards, which is also getting the background color from this.props.board.background. Now let's click on one of these and see if the push method will work. We now see your message off cannot read property push of undefined. This is not working because as we mentioned earlier, the package which we are important at the top of the file, which is called router, will now need to be a rapper for these components. We can do this pretty easily if we go down to our export, and then we can wrap our board preview components with router, and then inside here we can pass in our board preview, save this file, and then let's check this out over in the browser. We can click on any of these boards and then we take it to the board components. This is board number 2,000. Let's go back and try cause ideas. This is now board number 1,000. Also the same for the garden ideas. Later on in the course, when we get to use in Firebase, we will use this board ID to get the unique ball data rather than at this cargo diversion, which you see here. But for now this is a step in the right direction, and next up we'll take a look at how we can pass state using react router.
20. Passing state via router: We already know how to pass downstate when rendering components using the router, just like we did with this home components. We'll past the boards and also create new board function. Also in the board preview, we've navigated to a different route using the push method. Using this push method, we also sometimes have the need to pass down state to our new URL or to the component which is rendering. When we go over to the browser and then go back to our Home section, if we click on any board which you want to view, it would be a good idea to also pass the data to the ball components, such as the ball title and also the background-color. Over in the board preview, we can add state or add data just after the path-name. We can also set up a state object and inside here we can pass down our board information. First of all, I'm going to pass the title. This ball preview has access to all of the board information which is passed from the Home components. Let's take a look. This board preview is then receiving the board as a prop. Therefore, we can access this with this top props, the board. We can access the title. We can also pass down the background too in the exact same way. This is going to be this top props, the Board, the background. We can try this out over in the browser, save this file, and then go back to our board previews, click on any of these, then we can use a React developer tools. We can search for the board, which is the current components. Select this and now inside of the props, we can also make use of this location prop, which is being passed down via the router. If we open this up, we now have a state object living inside here. Let's drop this down and now have the background and also the title available to this board. The title is Board was course Ideas. So let's go back and also check the House ideas. Check the board, location, states, and now have the house ideas are title and also the background color. Now we know where our data lives in these components. We can now use it over in the Board. Let's head over to the board.js components. First, we can set the background color of the Board. We can add this to the opening div inside of our random effort. So let's add this to a new line. We can first add a class name and link this to the CSS, it's going to be Board wrapper. Then it just like we did with the board preview, we can also set up our styles, which is going to set the background color using camel-case, which we can grab from this top props, the location, the state, the background. Make sure it's spelled correctly. Before we go any further and add the title, we can now see the blue has appeared inside the browser. We can go back, check out the yellow course ideas. We'll do the same also for the garden ideas too. Passing the background color to our board. Just below this, we can also add a board title and also a delete board button, which you can use later. Below our div for the board-wrapper, we have the div with the class name of lists wrapper. Let's go above this. We can set to up a new div, which is going to be for the board header. So add our class name or hyphen header. Inside here, let's add a level three heading, which is going to be for the title. We can grab the board title using list of props,. location,.states and then the title. Just after this, we'll also add a button, which is going to be used later on in the course to delete the board. We won't add any click handlers onto here just yet. Instead, we'll just start at the text of delete board. Now we can save this and go to the browser. We have our delete board button in the corner and also our board title. A [inaudible] we have course ideas and also the House ideas too. Now our background color and also our board title has been passed to this board components using the state object via the React router. This is on our work in, so I will see you now in the next section where we'll get to work using Firebase.
21. Setting up Firebase: For this project, we're going to be using Firebase as the back-end. This will allow us to add a database to store all of our boards, lists, and cards. Also it will allow us to only get back the board's, list and cards we need for the currently log in user. We can sort them by the creation date. It will give us real time updates as data changes, and so much more. Also, we can use Firebase for user authentication, signing up and login in. Another great feature of Firebase is that it can be used not only for web projects, but also for iOS and Android too, so we can share the same data across multiple apps. We can get started over at firebase.google.com. You need to sign up with a Google account if you've not used this before. If you need to go ahead and sign up now. I'm currently signed in, so I'm just going to click on "Go to console". Before we go any further though, Firebase seems to change it's website layout and design pretty regularly, but the steps are usually similar. If it looks a little different when you visit, you should still be able to work things out, since there are only a few steps to take. The first thing we need to do is to create a project, by clicking on "Add project". I already have a project called React Trello, so instead I'm going to call this React Trello 2. We also need to accept the terms and conditions before we can create our project. Then give us a few moments to create. We're going to be using the latest Firebase database, which is called the Cloud Firestore, which will give us our real-time functionality. Real-time meaning our app can be updated with changes as they happen, and our data can be kept in sync across different devices, rather than us having to make a new request after each change. Once this is done we can click on "Continue", and then we're taken to the Homepage for our project. We now need to click on the Cloud Firestore, which we can get from clicking on this Cloud Firestore section just here. Or we can click on the "Database" from the menu. Send things up is pretty simple, we just click on "Create a database". We're going to start in the test mode, just for now, meaning and that's all users can read and write into our database. But we will add security rules later on. Click on "Next". We can then select our region which is closest to us. Choose any of these and then click on "Done". This is our database Homepage, and this is where our data will display once we push it to Firebase. We can also manually add collections to using this link here. A collection is a group of data which will be our boards, our lists, and our cards. Then add this database to our project. We need to first get our Firebase settings. We can do this in the sidebar and then click on "Project Overview". We're going to be using the web version, so click on this. We'll need to give our application a nickname. I want to also call this, React Trello 2. Then register our app. This will give us access to our config settings, which we need to add it to our project. We need to copy all of the settings from inside the config object. Basically, everything inside of these curly braces. Copy all of these lines of code. Then we can take these over to Visual Studio code. Let's create a new file. Open the sidebar inside of source, new file. This is going to be called Firebase.js. The next step is to install Firebase from NPM. Go down to the terminal, press Command or Control C if you need to close down the server, then you can run a command called NPM, I for install, and then the package is simply called Firebase. Now if we go back into our Firebase.js file, we can now do an import, pull in our Firebase package and store it inside a variable. Import this from the node modules. This package will be called Firebase. Then we're going to do forward slash up. Forward slash up is the core Firebase client, which is required when using Firebase. The next step is to also import the firestore package. We don't need to store this inside a variable, so we can just do an import without installing this by name, so we can import the Firebase package, then a forward slash Firestore. This will make the firestore functionality available in our projects. We're next going to create a constant called config. Config is going to hold all of the options which we just copied from Firebase. We can paste these inside here. Let's close the sidebar so we've got a little bit more space. It looks as though I've missed off the end of trello but it doesn't matter. Let's go down and now initialize our app. We can do this by selecting our Firebase variable, which we imported at the top. Then we can do a method called initialize App, then we're going to pass in our config object without settings from Firebase. With this configuration now taken care of, I'm now going to set up three constants, these will point to our database collections which is going to be Boards, lists, and cards. This is just basically a shortcut which we're going to use throughout our project, rather than having a lot of repetitive code which will point to the location in our database. First of all, we're going to create a constant called db. It's is going to be equal to Firebase.firestore. Again, this is also a shortcut. This is a pointer to our Firebase database, and now we can just type db instead of Firebase.firestore. Below this we're now going to create a reference to each collection we need, this will allow us to access these new project to save and retrieve data just by using the variable name. First of all, we'll create a boardsRef, and this is going to be equal to our database, which is DB, and I'm going to access a collection which we don't have yet, but this will have the name of boards. I'm going to copy and paste this into more times. The second one is going to be a reference to our lists. The collection name is going to be lists. Then the third one is going to be a pointer to our cards. All this means now is in our project when we want to push a board to Firebase or retrieve a board from Firebase, we just need to type the word boardsRef, rather than having to type out Firebase.firestore.collection.boards. Now we can export these references, so we can access them in the files. You can do this, with a named Export inside the curly braces. We can export our boardsRef, our list draft, and also the cards ref too. We can now save this file and test it's working in the app.js. We can begin with our boardsRef by importing this at the top of the file. Just below class we can create an import, we'll first of all import our boardsRef. This is from our Firebase file, which is a stringoff./ and then Firebase. This was a named export, so we can import each one inside of these curly braces. We can then add a quick test in the componentDidmount to check this is working. Just under our set states, we can now access this boardsRef variable. We can then call a method called dot add, which is a Firebase method to add new data to this collection. We're simply going to create an object with a name and a value of hello. Let's save this. Now if we go onto our project and then reload, we have an error of boardsRef. Let's check this out. We have the import, that looks correct, go over to Firebase, and this needs an S. Back to the project. Reload, and this will now cause the component in mountain to run. If we go to Firebase, and we can close this down, go to console, and into our database. We now see we have a board collection with a single document. This is the document's ID, then we have the name of hello. One of the benefits of using Firebase is we don't need to define our collections beforehand. We can simply push a new object or new item to Firebase, and it will also create the necessary collection and documents. This is just a test, so I'm going to delete this now. Let's go into our boards, delete the collection. We also need to type the board's name. We can remove this, and then remove the code from componentDidmount inside the app.js. Remove this line of code, save this file. Now this leaves us with Firebase on our setup. We're good to now move on to the next video.
22. Pushing data to Firebase: We now have five bays setup and we know our connection is now working. We can move on to creating our methods in react to then push data to Firebase, starting in this app.js. Here we already have a method set up to create a new board. So we can now use the Firebase add method to push our new board data to our database. Let's begin inside of this method just before setting state. We create a new constant which is going to be called the new board. We want to set this equal to our board graph which we imported at the top of the file in the last video, which will point to our collection of boards. We then going to use the add method to then push a object, which is going to be our board, which is passed to this method as a parameter. Firebase record will automatically get an ID generated. Before saving our new board states, we can construct a new objects where we grew up this ID and then add it to the rest of the board. Let's do this, just above our set state call. We can create a constant which is going to be called the board object. Here all I want to do is to grab the existing board data and also merging a ID. So first of all, let's says a ID property, which is going to be equal to our new board constants, then ID. Remember, new board will refer to the data which will return back from Firebase when we add this new board. Therefore it will also have the Firebase ID property. We can also add a comma and then use this spread operator to add in the rest of the board. Now when we set in the states, we instead want to add this new board objects. Next we can add some error handling to this method using async await. Async await will allow us to wait for the board to be first saved to Firebase before moving on to the next line of code. We want to make sure that the board is first saved because we need to access this generated ID before we can save it to state. First of all, we can set this function to be asynchronous by adding the async keyword. This will then allow us to add await into our method. The data which we want to awake and come back is this new board from Firebase. We can then add some error handling using try and catch. First of all, let's run this code inside of a try block. Open up the curly braces. When I'm going to close this off just after we set the state. Add an extra curly brace right at the end. If you're not used to try and catch before the try section is the code which we first need to try to run. If the code which is run is successful, all is good. If there is a error when running this code in the try block, we can then catch this error using a catch block. Just after this curly brace, we can also add a catch block, which is going to take in the error as a variable. Open and close the curly braces. We can then do a console error, which you're going to output a string of error creating new board and a colon. Then after this, we can also add a comma. Then we can also display this error which is passed in to catch, this to save. Then we can go over to our boards and we can try this out. Off to the browser into our projects. We still have a bar graph here. Let's go up into the boards. It's now over to a home components. Well, we need to add in a user, let's go for 1, 2, 3 and then forward slash board. Let's try this out by pushing a new item into Firebase. Let's go for a test board a color green, then creating a new board. This board is then immediately added since it pushed it to state. As we already know, state will trigger an update in all components which uses data. If we now refresh this, the data will be lost since we get this boards from states rather than from Firebase. Well, we can go over to the Firebase console and check this has been saved. Reload the console. Our test board is now saved inside here. As we mentioned before, Firebase adds a unique ID. Let's go to the Developer Tools. We can also check that this is being added to our state. That's our test two. Create a new board. You can now see how states has been updated to include four items in the array. Click on this, if we click on the last one, we now see this unique ID has been added to our object. This should be the same ID which is being provided inside the Firebase if reload. Then click on this. This is our test two with the same ID, which we now have in-state. Let's now do the same over in the board.js. We can push our new lists to Firebase two. Head over to our ball components. Then we need to look for a method called create new list. This is what we need just here. The first thing I'm going to do is to mark this function as a sink, so we can use a wait. Then we can add some error handling by adding a try block. Open and close the curly braces. We can then remove this curly brace and then add it down at the end. Just after we set our Ref back to an empty string, you can add this in. Add a catch block which passes in an error. Open and close the curly braces. Then we can pass a console error with the string, which is going to be error creating a new list. Passing in the error. With this error handling now taken care of, we now need to make some changes to our list objective. Let's scroll up. Here we have a list object which we created earlier. The first step is to now remove this ID. Since we're going to be adding this via Firebase. We can also remove these cards array since you no longer need this data. Let's remove this. We will be identity cards as a separate collection inside a Firebase, and then linking them together via the IDs. Now we should just be left with the title, the board, and also the created art. This list also needs to be linked to the color board, so we can change the board property to do this, rather than having a hard-coded value. We can now set this to be this dot props dot match dot params dot boardID. If we go to our board, remember, this is the data which we get passed from the react router. We can see this over in the developer tools. If we click on any of these, choose the board, then we have the props passed via the router, inside a match dot params. We have this boardID. Therefore this you're going to link the card which have been created with the current board. This will allow us later on in the course, to then pull in all of the lists from Firebase for the current board which we are viewing. Below this we have a statement. We can also make sure that the boardID is also present before we save this to Firebase. You can also add a list, a part because we don't want to save a list which has no relationship to a board. Now instead of saving this list to states, we're now going to push this to Firebase. Since we now deal with the lists, rather than boards, we need to import the list reference from o5 based file. We can do this by importing the lists ref, from our Firebase file, which is located in dot-dot slash then the filename of Firebase. Then we can add our new list to Firebase instead of using the set states, that you move this line. Instead we can add a weight into mark dysfunction as asynchronous. We can access our lists draft. We can then use the add method to add a new object. This new object is the list with retreated above. Now let's save this and we can test this out over in the browser, make sure you inside of one of the boards. Then we can now go and create a new list. Click on this, so course list 1 and also add course list 2 over to the Firebase console. After reload, now see our lists objects or our list collection has now been created. We have our two lists. The first one is linked to board 1,000 as is the second one. We can see inside of our projects in the URL that this is the boardID. Let's just go over to house ideas and other a new list 2. House list 1, we'll check this inside of the console. Make sure this has the ID of 2,000. There you go. The last thing we need to do in this video, is to create a new card. New cards are created in the parent list components. This will follow a similar pattern to what we've just done. There shouldn't be any surprises. Over to the list dot layers. We can first set the create new card method to be async. You can then wrap our code in the try block. Take off the closing brace, and then we can add this down at the bottom. Your stuff over console log, also add in the catch section, which you are going to take in any errors which are created. It generates a console dot error with the string of error creating new card, at the colon and then pass in our error. The only change to our card is the set the list ID. We can grab this from the list prompts, which are passed down, rather than is hard-coded value of abc 1,2,3 we grab these from our props, which you set via the list dot ID. Here we are creating a new card. We'll also creating a reference to the list, which it belongs to. If we go over to the list components in our projects and the reactive tools, search for any list. We can then see this list which is passed as props. Here we are grabbing the list ID, which is 100 in this case, the second one has a list ID of 300 and so on. The next step is to import our cards ref, from our Firebase file. Inside the curly braces. Grab the card's graph. The file path is also dot-dot slash Firebase. Just like we did with the list before, we can also go down to the if statements before push this to state. Then we can also add onto the end a second track, which is also going to check if the card dot list ID is also present. Since this is required before saving to states or to Firebase. The next step is to also remove this set state method. Instead, we are going to await cards ref dot add. We add this to Firebase, the object which we want to add is this card which we just constructed above. Parsing of a card, save this file and then we can test this in the browser. We can test this by adding a new card into multiple lists. Let's say house card one, house card two. This is for the travel ideas. Travel card one. This is card one, forward to Firebase and then refresh the console. Those are the cards. This first one is associated with the list 200. The second one is 100s, and also 300s. Everything is working fine. We also have the correct text for each one. We have a created update, which is been generated using JavaScript. We don't have any labels just yet, but we'll come back to this later on in the course. Now have the Firebase data to work with. In the next video, we're going to remove the sample data from our projects and instead read the data from Firebase.
23. Reading data from Firebase: The sample data which we imported earlier is no longer needed in our project. So we can now begin to remove it and work from our database. We can do this over in the app.js. First of all, we can remove the import, so import data, let's remove this line and then down below, we have a component did mount, which sets the state using this sample data. Let's remove this line too. In place of this, I'm going to create a method which will get our boards from firebase but only when we actually need them. Just below this component did mount, we want to create a new method called get boards. This is going to be a async function, which is going to take in the user ID, which is going to pass to it. Instead of our arrow function, create a try section and also a catch, which takes in the error, that you're still a console log with the error message of area getting boards and also passing in the error message just after this. The first thing we want to do when getting at the new boards from firebase, is to set the state to be empty. So inside the try block, we can do with this.set state and then inside here we can add our state objects, which is going to set the boards to be an empty array. This will just ensure that any previous boards and states will be removed before make a new call to firebase. Up at the top, we already have our board reference imported from firebase. So we can now use this to get the contents of the boards collection and we can do this by calling the get method. So just below the set state, we can start to obey constants with the name of boards and then we can await our data back by grabbing our boards reference and then calling the.get method. This will get the contents of our boards collection only once. It won't listen for any changes but we will look at how to do this later in the course. The board's constants, which we have just here, holds all of our boards, meaning you can then loop through them, get each one and then save these to our state. Firebase will allow us to do this by using a for each method and we can do this just below this line. We can select our board constants, we can loop through with for each. Inside here we're going to store each item inside of our boards into a variable called board. Inside of this function body, we can begin by doing a console log and then load the value of our board. Before we save this state, we're going to do a console log, since it can be a little confusing without seeing what comes back from firebase. To run this, we can temporarily add this method above when the component mounts. So inside here we can call it with this.get boards. Okay. Once this is done, we can open up the terminal, make sure that the server has started with an NPM start. Let's kick this off. We can then go over to the project and then if we right-click and then inspect, open this up in the console and let's do a refresh. Inside the console, we see what is called a query document snapshot, which is a snapshot of the document we're reading from firebase at that particular time. If we open this up, it does contain the board ID, which you can see here. We do need to grab this but if we only want the actual document data, rather than all of these metadata, which we see here along with the firebase references, we can change our console log to call the data method, which will extract all the fields as an object. So down in our console log, we can also add the.data method onto the ends. Also add the brackets to call this as a method. We now see our four board objects. We can open this up. We can open up the board and now we see the properties of background created at title and also the user. This is stored in a board object, which you can see just here with the calibraces. So we can drill down further by adding.board onto the end of our console log. Let's go over now and then on the end of data, we can add.board to access the individual objects, reload and then we take them straight into our object. This is the exact data we need. The only missing field is the ID, which we mentioned before but we can grab this directly from the board. Now we can store this data inside of a constant of in the app.js. So rather than this console log, we can now remove this, we can set obey constant called data, which is going to be equal to board.data.board, which we've seen in the console log and then we can create a new board object. Let's take this board data and then mix it in with the missing ID. On the next line we create a second constant, which is for the board objects. Setup our objects. First of all, we can mix in the ID. We can grab this directly from board.Id, then we can spread in with the three dots. The data, which is this constant from just above. Just after this object, we can now set the state with this.set state. Inside here we're going to target the boards object. We're going to set this to an array, so we're going to take a copy of the existing state, with this.state,.boards, separated by a comma, we can then add in our new board object, save this file and then we can test this over in the browser. This is a good start. We see the board's being pulled in from firebase. Let's add a new object or a new board object. Let's go to the react developer tools, search for our home component. We have our boards as props, am going to see the array with our four new boards. Let's try and add in one more. Let's go forward to do the color of orange, create new boards and now I have an extra object pushed to our state and this is constructed in the same way as all the rest. We've mixed in the ID with all of the rest of the board data. So currently we've added this call to get our board from firebase inside of the component did mount. We only want to grab these boards when the home component loads rather than the actual app, since this is where they're going to be displayed. All we need to do for this is to move the component did mount code to the home components. Let's cut the component did mount section. We no longer need this and then we can go over to our home components and then we can paste this in right at the very top, just above our random method. Since we now access in this get board method, which is in the app.js, we need to now pass this down as a prop. Let's scroll down to our router and then inside of the home link, which is this one just here, we can also add a prop called get boards, which is going to be equal to our method of this.get boards, save this file and now over to our component did mount inside our home.js, we now need to access this via props. So this is this.props.board and then add this to our prop validation down at the bottom. Get boards is going to be our prop types and this is a function which is also required to either come at the end. Then we can now save this and go over to the browser. Inside here, the boards are still showing in the browser, but they are now only loaded when we're viewing this whole components. If we go ahead and click on any of these, we still see our sample data inside here, and we'll fix this in the next video. When we created the link to this board earlier, we also passed this board ID via the URL parameters. We can now use this board ID to fetch the current loaded bar details from Firebase, rather than from our sample data. This will be stored into local state i.e. inside of this components, and will be used to display the ball title and also the background color rather than using the sample data which we see now. Let's do this now this is the board components will go over to the board.layers. Up at the very top were importing in the List Ref. So we also need to ground the reference to the Board 2. We are going to be loading up the current board so we can also add this state. So this is the current board. We can set this up initially as an empty object. Then now below we can also set up a custom method just below component did mount, which is going to get our current board from Firebase. Lets call this method. The get board is going to be a sync, and it's also going to take in the board ID. So we only get these single board from Firebase. We can set up our method at a try section. Also a catch section below which is going to take in the error. This is going to send out a console log with the message of error, getting boards, and also passing the error. So the first thing to do in the try section up here is to create a constant which is going to store our single board. We can await this information back from Firebase. This is in the boards Ref. We want to use the document reference, which is going to be the single board ID, which is going to pass in when we call it. We're passing this. Then we can call the.get method to grab all the contents from our board. Once we have our board we can now say this is state. With this set state, state which you want to update is this current board which you have just here. Set is equal to the value of our constants, and it's also needs to be board Ref. So make this change. So we don't want to set the state just like this. I'll make sure this is boards too just above the top. So currently we set in this board object in the state, but we don't want to do it just like we see here. Remember earlier when we got all of the boards over in the app.js. If we go up to the gap boards method, when we added a console log, we see that we got back a query snapshot. This is the same here so it can access the board objects, in the exact same way as this by colon need dot data method and then access in the board object. So let's do this now. We already have this board we can call.data and then access the board object just like this. This board data needs to be available immediately. So we can call it from component did mount passing in the current board ID. Let's scroll up inside of component did mount. We can now call get board inside here by using this.get board. Then we need to pass in the ID which is received inside this method. So to grab the current ID, we know this is stored inside of the URL parameters. Which you can see up at the top here, and we already know how to access the router parameters. We can do this with this.props, the prop name of match which is from the router. We're going to access the params, and then the parameter name, which in this case is called the board ID. Save this file and now over to the board inside of the browser. So as soon as this board component will load, let's go to the reactive tools and check we have the data which we need. Let's do a search for the board components. Select this inside the state we have the current board. Let's open this up and now we see all the data which we need such as the background-color and the title. So we can now use this in our random method inside of the board to set the title and also the background. So let's scroll down to the random method. Then the first thing to do is to set the background color. So rather than using the router props, let's remove this, and then instead we can use the data which is stored in state. So this.state,.current board. We can access the background property. Just below inside the level three heading, we can access this.state dot.current board and then it grab the title. Check this is still working over in the browser. Load at the board components, and we still see the title and the background color. When we go into each one of these boards. With this now working we can go over to the board preview components, and also remove the state which is passed down by the router. So this is no longer needed. So can remove these state objects and leaving just the path name for the redirect. They should still not working okay inside the browser. So you may have noticed that this was all working completely fine before we had the background color and the title passed by the router. So you may be wondering why changes at all. The reason is for updating the components. Before we passed the ID and background to the board component. This meant that once the board was loaded, we then stick with it this exact data. However, when fetching the board data from Firebase and storing it in this state, this will mean that later on when we update the board such as the title, any changes will then be dynamic and also update the component two. So it is now in place, let's now move on to the next video.
24. The where & orderBy methods: With what we learned in the last video, we can now apply this again to retrieve the lists and cards from Firebase. We also going to be taking a look at two new Firebase methods. One is called orderBy and it will sort our data, which we'll get back. Then the Where method will allow us to only get a list or a card, if the boardId matches the current board we're viewing. Let's start over in the board components. The Board.js, we can start up at the top by removing the sampleData, we no longer need this import. Therefore we can also remove the setState call, which will apply this to state. Now if we go over to the browser, on the board view, it's no surprise we don't see any lists or cards in this components. So let's replace our sampleData with a method called getLists of in the board components. This is going to get our lists from Firebase, just like the getBoard method below. This one is called getLists, and this is going to be equal to async function which is also going to take in the boardId. Setup the arrow function, then inside here we can create our try and also our catch block. Catch block takes in an error as always, and then we can do a console log with the string of error fetching lists. Then afterwards, I'm going to add a comma, and then also I'll put the error. So just above this try section, we can first create our constant which is going to hold our lists. Where we going to await our list coming back which we can grab from the listRef. We could now chain onto the end the.get method which we used previously, but this would go ahead and grab all lists in our database. Instead, we only need to get the list for this column board. Over in Firebase if we go back to the browser, and then to the Console. Remember earlier when we created a new list and a new card, we also added a ID. This list, for example, has a boardId of 1,000 and then this will link to a individual board which it was created on. Firebase allows us to do this using the Where method. Let's take a look at how we can do this. Just after our listRef, we can chain on the end the Where method. Then inside here, this takes in three parameters. The first parameter which we add in is the field name. The field name is going to be equal to list of board, since we are looking at the list objects and then we want to select the board property. Inside here as a string, we can pass in list.board. The second parameter is the comparison, here we can use less than, greater than or equals, just like we can with JavaScript. Separate it by a comma. As a string, we can add the double equals to compare this board reference with the boardId which is passed in to our function as a parameter. Now this will only grab our lists from our collection, where the board field will match the current loaded boardId. This list also has a createdAt field. If we take a look in the console. This is the createdAt field just here, and this can be used to order our data by the date from when it was created. I have a spelling mistake here, but that's not a problem since we can delete these and then create a new list later on. Let's take a look at how we can use createdAt inside of here. All we need to do is just have to where, this we can also chain on to the end the orderBy method, then inside here as a string, we can pass in our list object and then the field name of createdAt. This will sort our list into ascending order using the createdAt field. You can also use any other field here too. If you want it to have the order reversed, you can also add a second argument of descending which shortened to D-E-S-C. But I want to remove this and keep it as default. We have error down the terminal, so this needs to be boardId, just like we've pressed data into our function. Then finally, we need to call the.get method to finally get these data. The rest should be pretty straight forward as is similar to what we've already used. Just after the Get method, we're going to call our list object, called.forEach method, so we can move through each item inside here. We're then going to store each item in the list variable, and then this runs a function for each one. First of all, let's grab our data, with const data and I'm going to set is equal to list the data method which we looked at in the last video, and then select the List object. Just after here we're going to construct our actual list which we can then push to state. Remember when we did this to the boards of in the App.js, we stored the data into a variable, we then created a board object where we had the data. We also needed to merge in the ID, which wasn't available from this data method. We just do the same over in the board, we can create our list objects. This is going to be equal to our ID, which you can grab from list.id. Then we use the spread operator to merge in the rest of the data. Below this, we can then set the states with this.setState. The state that we want to add is the currentLists. We have this already setup as an empty array. Let's set this inside here. We're looking for the currentLists, they're going to be equal to an object where we spread in the current state with this.state.currentLists separated by a comma. We then merge in our list object which we just created. Now this method is grabbing our currentLists and filtering them to the column board view. The next step is to actually call this method when the component will mount. Let's do this with, this.getLists. Remember getLists will also need a boardId, which you can pass in as an argument using this.props.match, to get this from the browser. We want to select the params and then also the boardId. Save this file and head over to the browser and then go to our Projects. If we open up the Console we see a strange warning. It tells us that the query requires an index, and then we can follow this link to create this. We can click on this link which it provides and then it will take goes over to the Firebase console where we can create a new index. We can see here that Firebase is going to create an index for those on this list collection. We can also see that the methods which we just added are also taken effect onto these fields. We assault in the list of boards into ascending order and also the createdAt property into ascending order too. We can go ahead and create our index by clicking this button. This is required since we now perform a more complex query. Remember we are using the Where method to filter out documents by the boardId and we then sought them by the creation dates. An index is a way to structure our data to loop Firebase to locate our data more efficiently. Resulting in our query being performed much faster, it basically will make Firebase aware that at some point in the future, we will be forming a more complex query so Firebase can be ready for them. This might take a little while to finish. Pause the video and come back when this is all done. Welcome back. Once this index has been created, now will be a good time to delete all of the lists and cards we currently have in the database. Let's head over to there and we start with the lists. I'm going to click on this icon and delete the collection. Also type in the name of lists to confirm this, and also the cards we can do the same. [inaudible] remove this. This is because they are linked to the boardIds from the sample data. I'm no longer using the sample data, therefore we don't need this. Now if we go back to our application, let's reload, and then we can create some new lists. Let's add List 1, List2, and then refresh. We see an error now saying cannot convert unidentified or nulled object. The reason we're seeing this error which is related to this.props.lists.title over in the list components is because we are still trying to loop through cards, which we don't have yet. Remember earlier on when we had our sample data, we had some cards added as an array inside of each list objects. We no longer have these values, so we can now remove this from the List.js. All we need to do is to comment out our loop, which is this section here, which is rendering out a card component. Over to the browser and now we can see the two lists which we just created. Let's also create some cards, card 1, card 2 We can add this list two as well, so card for list two. We won't see these cards just yet, because we just commented out the card components, but if we go over to Firebase and then refresh the console, first of all, let's check out the lists. If we click on these, these are now linked to a particular board. The same with our second one, and if we go to our cards, we can also see these are connected to a list ID to the third one, and this is a different ID to the first two. To finish off this video, we can now read the cards from the database, which will follow a similar pattern to our lists. Over in our list we got JS components, we can first call the method from inside of component did mount. Just below our state object, we can add componentsDidMounts, setup our brackets and our curly braces. Inside of here we can call this.fetch cards, which is the method we're going to create in just a moment, which is going to pass in the list ID with this top props fault.list. Then we can set up our custom method just below this, so this is fetched cards is going to be a sync function, which you're going to take in this list ID which would been passed to it, setup our arrow function. Then I try and a catch block. Passing the error, not a console.error with the text of error, fetching cards. Add a comma and then outputs our error, so now we can set things up to get our cards from the database, which will match this list ID which is passed in. We can do this inside of the try block. We're going to first create a constant to store our cards, where we are going to await the data from our cards ref. After days, we can add train onto the end D taught where method. Remember this takes in three arguments. The first one is the value which you want to compare against. This is stored inside of the cards. If we take a look at the console, we want to select the list ID, so select card.list ID. The second value is the comparison, which is equals. We want to check if this is equal to the list ID. Just after this, we can also chain on to the end the order by method. We want to order this ascend in by the card.created up property, and then finally, to get this data, we call the.get method. After this, we can then select our cards and then loop through each one with the.for each. For each is then going to store each value into a variable called card. This will run a function which is going to construct our card objects. First of all, we can grab our data, which is just like we did with the lists on the boards. We can grab our card objects. We can run the data method to grab all the properties from the card and then select the card objects. Next, we're going to then create our card objects, which is going to be the one, which will push the state. We need to select the ID, which is available from the card object.ID, separated by a comma. We can then merge in the data, just like we did with the lists on the boards. Let's test this is working with a console log after our object. We want to log the value of our card objects. Save this and then go over to the browser into our project, we can now reload, and then we see that this query also requires an index two, so click on link over to the console, and we can now create our index for the cards too. Let's create this with this button. Pause video and give us a few moments to build our index, and I will see you in a few minutes. With our index is now created, we can go back over to the app and then reload, and now we'll see all three cards have being placed into the console. That's try creating a new card, test. Number one, send this off, reload the browser, and now we'll have our fourth card just added with the text of test one. We can also see this is linked to this list ID. Let's try adding a new one, so test two reload, and then we can see that test two has a different list ID to number one. The next thing to do now we know we have the correct data is to replace our console log with a set state. This now set states. Inside here we're going to set the current cards, which we already have in the states, create our objects. We can then merge in to our states. Our current cards, also passing in our new card object. With this now let's go back over to the browser, and then if we search inside of the react developer tools, we can search for a list components, select one of these, and then it down on the bottom we can see our state of current cards. This has an a ray with two different cards inside here. You can search for our second one. Uninstall the three current cards related to this list, so the final thing to do in this video is to display these cards inside of each list. If we go back to all list components and we can count out this loop which will run the out of the cards. We can then change the style prompts to be this top state. Since we now store in the current cards into states. Exactly the same before as our data. This is going to be this.state,.current cards, also passing in the key, over to the browser, and now we'll see the lists. Now have the cards display in each one. This now leaves us with each card on the correct list, and next we're going to look at how we can delete data.
25. Deleting cards and lists from Firebase: We now move on to adding the functionality to remove our items from the database. Removing one item from Firebase is pretty simple. All we need to do is to find the item in the database and then call a delete method. This is what we can do for the cards. The first thing we need to do is to add a simple Remove button for each card, which I'm going to add as a simple cross over to the Card.js components inside of our div and just blow the context. We can add HTML span elements. Inside here we can add a onClick event handler, which is going to trigger a method called this.deleteCard. Inside the opening and closing span tags, we can add HTML entity, which is the ampersand times and then the semicolon. Also the browser. This will output a cross, which we can use to trigger this method. Now we're dealing with the cards stored in Firebase. We need to import the cards reference. Up at the top, we can import our cardsRef. This is from the string which is../firebase. Then we can create our deleteCard method, which is called by clicking on this cross. Just above our random effort. We can add deleteCard is going to be a sink. We will receive the event information. When it's called settled the arrow function. I will try section and also the catch passing in the error. We can now put a console.error with the string of error deleting card. The first steps up in the try section is going to use this event information to prevent the default behavior. Will then need to grab the cardId from props. We can store this in a constant called cardId. Unsat this too this.props.data.id. Remember each card is receiving the props called data. So we'll go into the developer tools into React. If you search for a card, this is receiving all the data for each card Inside of this data Props. Here we access in it this id. Now we can use this to access a particular card inside a Firebase with this id. below this crazy new constant, which is going to be for our card. Here we're going to await the cardsRef point to our collection. We can then select a particular documents by the id. We already have this cardId stored just above. The last step is to then call the delete method on this particular card. So card.delete which is provided by Firebase. Let's save this and go over to the browser. Let's click on "Test one." We still need to refresh since we don't have real-time functionality just yet. But we now see that test one has been removed. If we go over to the console and then reload this, we can check each one of our cards for test one. This is now being removed from our database too. Next, we need to also remove the lists. This is a little more complex since we also need to find and remove each card, which is also associated with this list. Let's do this over in the list component, which is list.js. Again, this also needs a button or across to remove the list. We're going to do this just after we output the list title. This line of code just here at the span. The contents is going to be the HTML entity of ampersand times and the semicolon. This will also need a onClick event handler, which is going to be this.deleteList loop at the top. We can also import our listsRef from Firebase. Then created this deleteList method. This is going to be async and then pass in a arrow function, a try section. We can catch any errors at a console error with the text of Error deleting list. The first steps in the try block is going to be to grab the listId. We can store this in a constant called listId. This listId is available on the props. So this.props the props name is list. Then we can grab the id. Blow is a second constant for our cards where we are going to await our cardsRef. For this, we don't just want to call the.getmethod. Since this will grab all of our cards in the database. We only want to remove the particular cards which is associated with this list, which will remove in. Let's note this down. We can chain onto the end, the dots where method. Remember this takes in three arguments. The first one is going to be the card.listId. The second one is going to be the comparison. Would I want to check if each list id property on each card is going to be equal to this listId from props. So at comma, add in the listId. Then we can finally chain on the get method to pull in these cards. Next step, what you want to do with these cards, once we get them back. Well, for each card, which we get back, we want to call the delete method. But just before we do this, we're going to add a quick if statements, which is first going to check if any cards have came back. If cards.docs.length is not equal is not equals to 0. We then add the card braces. This is basically checking if the length of the documents which has been returned is greater than zero. This means that we have some matches for our list id. We can then loop through all of the cards.forEach. Then for each card we're going to call the.deletemethod. We can do t his with card.ref.delete. These should take care of removing all the cards which are linked to this list. The next step is to actually remove the list. Just each card section is going to be a little simpler. All we need to do is create a constant which you're going to grab our list from the listsRef. The document which you want to grab is the one which is equal to this listId. Let's pass this in. We can then use this list and call the Firebase.delete method, which will move the list too. Now we can save this and we can test this in the browser, over to Chrome and into the project. Let's go for List 1. This should remove Card1, Card2, and test two. Click on this. We don't see any errors in the console, so that's good. Let's refresh. Now this has been removed. Over to the the console. Let's first check our lists. We now just have List 2 inside here. The list is being removed. We can check the cards. Now we'll just have this single card, which is from this list here. This is all now work in. We can click on a list to remove. It will also remove any cards which has been linked with the id. Next up we're going to be coming back to deleting items by also removing the boards from our app and also from Firebase.
26. Deleting boards: Deleting the board is a little more involved than the last video. Let's not feel we have not looked at yet. This is because we need to find the board itself. Then all of the associated lists and cards which belongs to the board. Before then deleting in all three of these collections. If we go to the board view, we already have a Delete board button up at the top. All of the, board related methods and also the ball state is then kept over in the app.js. Someone's added a Delete Board method inside here too. Who then goes pass it down as props to the ball components., so it can be triggered when the button is clicked. The first step is to create the Delete Board method, which will pass to it the board Id. Let's go down just above the random method. We can create our Delete Board. This is going to be async. We're going to pass in the board ID when we call this and then setup our arrow function. First of all, we can create the try and catch sections. Passing in the error as always. Then we could do a console.error with the text of error deleting board, a colon, and then pass in the error. Since we are calling this method from the button in the board components, we need to pass it down as props. Let's scroll down to our router. We need to find the board components. Which is just here, just after the router problem, we can pass in delete board, which is going to be equal to our method of the stores delete board. If we go over to the board.js, before we forget, let's add the proper validation. We need to import this since we have not used it just yet, import the prop types. Then down at the bottom, we can create our prop types just above where we export this file, so bold B, prop types, setup above objects. The only prop which we get in at the minute, is going to be the delete board. The Delete board is the prop type of function, so we use.func. This is also going to be required too. Inside of the random method, we already have a button to add on click ''Listener To.'' Let's scroll up and take a look for our button and which is this one just here. We can then add on click inside here. This is going to trigger a method, so let's create this.Delete Board. This totally board is not the method which will pass down because we have an access this via props. Now we can go ahead and create Delete Board just above outside the random method. Delete board method, which we're going to add now, is going to be responsible for grabbing the ID of this current board. Then call in need Delete Board method which is being passed as props, so let's add this Delete Board. This is a async. Then inside here the first thing to do is to grab the current board ID and install this inside of a constant. board ID is going to be available from props. This top props.match.params.boardId. Remember, match.params, is the router props, and the params is going to be this board Id, which you can grab from here. We store this inside a variable, therefore we can now pass this when we call our Delete Board method, which we just created in app.js. This top props, totally board, as in the board ID. Before we go any further, let's test, this is all working. Over in the app.js, we don't have any content inside of this try section. Let's do a simple alert with the variable name of board ID, which is just being passed. Save this over to our projects. Let's try deleting the board. Great. Now we get the alert with the same board ID which is in the URL, when all the method is now being called. We can now use the ID to grab all boards from Firebase, update the state, and then finally the delete the board. Step one, we're going to move the alert, and then we can save the current board to a constant. We can do this by awaiting our boards Ref. Grab the document, and the document which you want to grab is by the ID. The ID is stored inside of the board ID variable. The next step is to update the state with this.set state. Inside here you can pass in our state object where we're going to update the Boards inside the State, will set this up as an array. The first thing is to use the Spread Operator to grab the current state of this state boards. This will take a copy of all of the board's currently in states, but if we want to remove a particular board, how can we do this? Well, we can use a JavaScript Filter method, which will filter out any particular Board from States. Inside here, we're going to store each board inside of this variable and then run a function for each one. This function is going to be responsible for only returning any boards from States which doesn't match this board ID. Let's add our return statement. We want to return any boards where the ID is not equal to this board ID, which we just deleted. Step number three, just outside of this cut section, we're going to call board.Delete to remove this from Firebase. We don't want to test this out just yet, because we also want to remove the lists and cards for this board at the same time. Let's begin with the lists, so over the top of our trying section. We can start with creating a constant called Lists. Inside here we're going to await our list graph, which is our list collection. Inside of this list constant, we want to filter down all of the lists which are related to this board ID. We can do this with the web method. It takes in three parameters. The first one is going to be the list.board. The second one is equal to as a string, and then the third value is the board ID. This is going to filter out all of our lists where the board property is equal to the board which was passed in, then we can find the grab all these weighted, they.get method. Since we now using this list draft, we can now go up to the very top of this file where we added the import and also at this too, then back down to our method. With this list data, which we now go back, we now need to do two things. First of all, we need to add an if statement to actually check if there are any lists saved this current board, before we go ahead and delete them. Number 2, if the list available, we need to look through them and then delete. Just under Get, we can add an if statement. We can check if lists, docs dot length is not equal to zero, then the code inside of this if statement will only run if there is more than one list. If these lists, we can then leave for you with the for each method. For each, we're going to store each item inside of this list variable, sets up a function for each one. Now this leaves us in a similar position to the last video. We have lists we need to delete, and we also have to find the cards for each list too and then go ahead and delete them. Meaning we now have some shared functionality. If we go over to the list app.js and then take a look for the delete list method. We created this method in the last video to do this. So rather than duplicate it, we can lift this up to the app.js and then shall the use of this function. Let's start by cutting out the full method. Will be closing curly brace up to deletelist hosted app.js. Let's paste this in and just above the clipboard. This method uses the firebase cards href, which you can see if we scroll up just a here. We need to import this at the very top and then back down to this deletelist method. Hope at the very top here we have a constant called listId. This line is getting the data from props, but we don't have this list proper available now in this app.js so we remove this line. and then instead when we call, this method will pass in this listId. This in the brackets. Since we removed this deletelist from the list components, we now need to pass it back down via props. Let's go down to our board. Inside of the router. You can then add this as a prop. This is the deletelist and this is going to be equal to this, dot deletelist. Then go to the board app.js. We can add these in as a prop type. Let's duplicate this and this was deletelist. Link list was down inside of the list component. Now we can pass this down as a prop inside of this list components. Just after a list, we can also add our deletelist prop, which is going to be available from this top props, dots deletelist. Now we again have this deletelist functionality available in the list. This is now receiving this as props. We can add it into the prop times at the bottom. This is the deletelists. The prop type is a type of function which is also required, add a coma in between. Inside of the random method for this list, we have a span element which is calling our delete list method. We can recreate this above to call the method which you pass down as props. Outside render, we can create our new method called list deletelist, setup our function and then inside this function we want to do two things. First of all, we want to grab the listId. Because remember from before over in the app.js, When we moved over this deletelist method. Let's scroll back up. We also pass this in as a listId. This listId is available inside this list component via props. This top prompts dot list dot id. Then we can finally go ahead and call our deletelist method with this dot prompts. Dot deletelist, which is going to pass in the listId. Save this file and before we go any further, we can test this list is being removed and issues wants to be lists-ref and the app.js. Let's add an s inside here and also 63 and 67. That's on the end. Also here too. Good. It is now working. Let's try to remove a list. Let's add list one inside here. Refresh, click on Next. Now if we reload this, this has now been removed. Let's also try one of these into different components. This new click on Next. Now we can also remove this too. Now this was a little bit of extra work to get this into different components. But it means we can now go back over to our app.js where we originally started and then we can make use of this deletelist method for each list which we have. Now we're looping through each one of the lists or when it's now do is call this deletelist method, which we now have available in this component. This dot deletelist. Deletelist also needs to be passed in an id and firebase storage this inside of an object called ref. We can access this with list dot ref, dot id. Now we just need to give this a test and in fact, this responds to be our list constant rather than our list ref. It gives us a save. Now if we go into one of these boards, let's go for our Test 2. Inside a here we have a list of one, two and three and also the cause of a, b, and c. Now if we try to delete our board, let's refresh. I will now see all the data has been removed. We can check this out over in the firebase console. Let's check our list on our cards have been removed too. Lets first start with our lists. We only have the single list on here rather than number 1, 2 and 3 in our cards. You still have the single card 2 and we don't see a, b, and c. This is now all of the deleting methods which we need for this project and in the next section we will look at how we can update our data inside a firebase.
27. Updating data in Firebase: In this section we're going to be focusing on updating our boards, lists and cards. This is important since a user may want to obey things such as a board title or a label on a card. Those labels are something which we'll get into Zoom. In this video, we're going to be making the board and lists titles both editable after we click on them. Then we can make any changes and push them to Firebase. Lets start over in the board.js then we can work with our board title. Here we're going to be replacing the current board title with HTML input element so the user can then type into it. Let's begin by removing our level three heading so let's remove, or comment out this line both. Then inside here we can create a HTML input. Then on the next line I'm going to add the type which is going to be equal to text. Also, a name, which is going to be the board title on change, which will trigger a method which is going to be called update board. The last attribute is going to be the default value and the default value is going to be equal to this.state.currentBoard.title. This is going to grab the title just like it did above in our level three heading. Using the default value rather than just the value attribute, we'll specify the initial value. We'll then leave subsequent updates on controlled so we can therefore edit this field. I'll save this file and then go over to the browser, into our projects. We need to go back, select the board. We can now click on its title and edit it. Of course, this won't be saved to Firebase at the moment because we haven't created this update board method which we call an inside here. Let's do this outside of the render method. We can create update board, passing the event information and then sets about function. This actual board update will open the app.js along with all of the overboard auctions. Let's begin a bigamy in the board Id and store it inside of a constant. The board Id is available from this.props.match.params.boardId. This is a board Id which is available from the URL parameters. We store it inside of this variable. Let's now create a new constant which is going to be called new title. This is going to store the value which the user typed in. We can grab this from e.currentTarget.value. Next, open grades and if statements where we can check if the board Id is present and we also want to check if there is a new title. If both of these are present, we want to call a method called update board, which we're going to create an app.js in just a moment. This will pass down as props so we can access with this.props.updateBoard. Then we're going to send to this method, the board Id and also the new text which is saved in new title. Let's now go up to the app.js and we can create this update board method, which is going to be responsible for saving this to Firebase. So outside of the render, update board is will be asynchronous. We'll say again the board Id and also the new title. We can settle back trying section then the catch just afterwards. Passing in the error where we can do a console error with the text of error updating board, also passing in the error. Good. Now, the first thing to do is to grab the board from Firebase using this board Id. Install the semi constants called board. We have our boards ref, which points to our collection. We want to target a specific document and this document is going to be equal to the board Id. The next thing we can do is call a Firebase method called update. Then inside here we're going to pass in an object. The field which we want to update is a title and this is available with board.title. I'm going to set this to the new title which is passed in. Now we've created this. We also now need to pass this down to the board components. Since we call niche from the board.js, let's pass this in as props. This is update board so they still update board over to the boards.js. You can also add this to of prop types down at the very bottom. This is update board. The prop types, this is also a function which is also required to save this file now over to the browser. Let's shrink this down. I don't want to put this side-by-side with the Firebase console so we can see this updating in real time. The console, let's select our to-do board which is this one just here. Click on our title. Let's try to add some different texts into here. I'm going to see this updates immediately. We can remove this. Let's try to refresh. If we now reload the browser, we see this data will persist after a reload. Changing the list title is also very similar to, if not even simpler since I'm going to be adding all of the code into list component so there is no need to pass it down props. If we go over to the list.js, we can replace our p elements with an input. Scroll down to the render. Rather than our p elements, we can remove this and HTML inputs. The type is going to be equal to text. We're going to also add a name which is going to be the list title. On change this will trigger a new method which is going to be update list then finally the default value. This default value is going to be equal to this.props.list.title so we going to grab this from above then we can construct the update list outside of the render method. This will be a sync taking in the event information. First of all, as ever, we add our try section and I will catch for any error handling. The console error is going to be a string of error updating list also passing in the error just afterwards. Update list also needs access to this list Id so let's crop this constant from just above. We can then add this in. A second constant of new title which is going to store in the value, which the user has typed in. We can grab this from e.currentTarget then grab the value which the user has entered. Next, we grab our list from Firebase and store it into a constant called list. Let's await the lists ref. We can grab a document by the ID, and the Id is stored just both in list Id. The final step is to call the update method with list.update. Inside here as an object, we're going to update the title field which we can grab from list.title and set this equal to our new title. Let's give this a go. We need to go over to the browser and find a board which has a list. Let's go back list two, let's click on this and change it to be list 200. We can also check side-by-side. List 200 American cities has been updated inside here. If we refresh, this now stays persistent inside the browser meaning this is now been stored inside a Firebase and we're now retrieving this in our list components. That's enough for updating the board and list. The card update, we'll have a little bit more to it. We'll begin this in the next video by creating a pop-up modal to make our changes.
28. Edit card modal: On the finished version of the project which I have opened here, if we click on any of these cards it takes us to a proper modal. This modal will allow us to edit the text on the cards, and also to add and remove labels too. Labels are something which Trello uses as a tagging system. As an example if you wanted to visibly see all of our cards which we've completed, we may want to add a green label to show this. This modal is going to be a new component to handle all of this, and this is what we're going to go ahead and create now. The styling for the modal has already been provided in the CSS styles, which you should have downloaded earlier. Just added some basic positioning and styling so we can focus on the HTML and JavaScript inside of our component. Let's start by creating this over in the components folder. Let's create a new file called EditCardModal.js extension. This component deals with props but for now, I'm just going to create the basic markup, and then we'll come back to and edit this soon. Let's begin with importing React. Then we can create our class base component which is going to be called EditCardModal. As ever this is going to extends React.Component. Inside here we can set our initial state, so it's a bubble object, and then the first piece of states which I'm going to add is for the available labels. This is going to be an array which is going to contain six different values, for the colors which are available to select. The first one is a hex value of 80ccff separated by a comma, I'm then going to copy and then paste this in five more times, to give us six different values. This second one, this is going to have the value of 80ffaa. The third one, this is going to be f94a1e. The third one is going to be ffb3ff. Number five is going to be bf00ff. The last one is ffad33, separated by a comma. We can also add a empty array, which is for the selectedLabels. SelectedLabels will hold each one of these values once a user clicks on them. Below this after our states, we can add the render method inside here, and we can return our jsx. First of all this is going to be surrounded in a wrapper, which is going to be contained in a div. The class name is going to be equal to modal-wrapper. Close this off. Inside here we can nest in a second div, which will have the class name of modal-body. This modal-body is going to have a form section. Let's take a look at the finished version, click on one of these. This modal is going to have a close button at the top right, which when we click on this will return us back to the board view. We're going to add a title, then we're going to loop through these available labels which you just set the state, and then display these. After this we'll have a edit area where the user can edit the text for the cards, followed by the selected labels which was the second item in our state, and then a submit button to save these changes. Let's go ahead and construct this now inside of this div. First of all inside here we can add a form nested inside. We're going to add a div and this is going to be a div for the first section which is for the available labels. The top of this modal section had a cross which a user could click on it to close down the modal. We can add this with a HTML entity which is ×. This is also going to have a className, to provide the CSS of modal-close. Just close down the sidebar to give us some more space, and then just after this span, a p element which is going to be for the text of add / remove labels. This also has a className, which is for label-title. Just after this title we're then going to loop through each one of these items in the array. Since it's now JavaScript to open up the curly braces we can access the available labels in states with this.state.availableLabels. We're then go to map through each one of these six values stored on each item inside of this label variable. Inside here we can return a HTML span elements for each available label. Close this off. The span is going to have a className, which is going to be equal to label. The key parts of this span element is going to be a style property. The style property is going to give the label the background color which we have set in state. Down just after our label we can set the style, open up the double curly braces, and in fact lets add this onto it's own line so its more readable. Inside the curly braces we can set the background to be equal to the label. Then to finish off this div section with a horizontal line, so the hr elements just below this div. We're then going to add a second div, which is going to be for our second section. The second section if we click on any of these, it's going to be this edit area. We're going to have a HTML entity which is going to be this little pencil, and then we're also going to have the input where the user can change the card text. Let's add this now. This div is going to have a className of edit-area. Then the first thing is going to be a span for our HTML entity. The className which is edit-icon. The HTML entity for the pencil is the ✎. After the span we can then add the input which is for the text. The input also has a className which is going to be equal to textbox-edit. This is all we need now for this section. After this text area div we're also going to create a third div section. This is going to be for our labels which the user has selected. Let's start with a p element which is going to have the title of labels, followed by a colon. P elements has a className, which is going to be equal to label-title. Then afterwards we're going to add some JavaScript which is going to loop through all of the labels, and then display them on the screen. For now though I'm just going to add a TODO section, and then we'll say display labels, comment this section out and then we'll come back to this in a later video. The final thing for this form is to add a button. This button in is going to submit the form so it needs the type of submit, the text of Save changes. Then finally for this component we need to export default the name of EditCardModal. Let's give this file a save and then we can go over to the card.js component, where we can import this new file. Up at the very top lets add this, which was the EditCardModal from./EditCardModal. Scrolling down into our random method we can now output this into the browser. Let's do this right at the very end. This will be called EditCardModal, close this off. Now because we have two elements side-by-side, we also need to add this in a fragment, so React.Fragment. We can then take the closing tag and add this to the very end. If all goes well we should now see this over in the browser. If we go to our project, and then we need to add a card, let's quickly add some lists, so abc, refresh and let's add a card, 1, 2, and then 3. We now have some content on the screen we have all of the labels, we have the text area, and also the label section at the bottom. We have the cross to close it down and also the button to save the changes. Obviously none of this will work just yet, and we also only want to show this when the card is clicked on. [inaudible] we can add a Boolean value to our local state over in the card.js. Up at the very top we can add some state so it's a bubble object, and then we can set the initial state of modalOpen to be false. Then below this we can create a new method which will toggle this between true and false. Let's call this toggleModal, so it's a bubble function, and then we can toggle the state with this.setState. Inside of our object the state we want to toggle is modalOpen. We're going to set this to a value of this.state.modalOpen. We can then add the exclamation mark just before this, which will do the opposite of what is currently set in state. Each time this is clicked it will take what is currently there, and then do the opposite. We want this toggleModal method to be triggered each time the card text has been clicked, so we can add a click handler onto the text below. Into our random method, the p element. We can then add a click handler inside of the opening bracket, and set this equal to this.toggle.Modal. Remember inside of this card is where we're going to render out our modal. This modal needs to be aware of this toggle state, so we can pass it down as a prop, so modalOpen. We'll set this to this.state.modalOpen, save this file and then we can head over to our modal component. Now this prop can be used to set the display type using a JavaScript [inaudible] operator. Let's scroll up to our modal wrapper which is this div just here, and then just afterwards we can set the style, lets add this onto a new line. We can set the CSS style property with the double braces. We can set the display type of this modal to be equal to this.props.modalOpen. If this Boolean value is true we're then going to set this display type to be equal to block. Or if this is set to false we'll set the display type to be none, which will hide this modal component. Now let's save this and then test this over in the browser, into our project. We immediately see that we have our cards and list, but we don't have the modal component displaying. Let's try clicking on the text, which will now trigger this method and open up the modal. However though if we click on this x in the corner to remove, it does not work at the moment. For this we also need to pass down this toggleModal method, so let's go back to the card.js. We have this toggleModal, which is just here. We can also pass this down to our EditCardModal as a prop. On a new line, we can add toggleModal which is going to be equal to our method. Back over to the modal components, we can now trigger this method when the x has been clicked. This is the span which has the x. We can add a click handler just like we did before, which is going to run this prop, so on click. We can set this to this.props.toggleModal. Back over to the browser we can now give this a go. Let's click on the modal which should pop this up. Then click on the x in the corner which now runs the toggleModal method and then sets the state to be the opposite which is false. This has now taken a little bit of typing to get this modal working. All we need to now do is to connect it to some methods to edit the card, and this will be our task in the next video.
29. Updating the card text: Inside of our project, if we go over to the React Developer Tools and then search for the card components. If we select any of these cards, we can see over on the right-hand side we have this data prop, which is available to each one. This contains all the information about the current card, such as the created at date, the ID, and any labels which is stored inside the Firebase. Since the modal is going to be responsible for changing or updating all this data, we need to pass this data down to the modal components. Let's do this by first going out to the card.js. Then inside of the edit card modal, we can then add a third prop to this, which is going to be called the card data. Then we can pass this data down as props. This. props.data, then we go over to the edit card modal. Remember when we created this component will be in states, we also created a selected labels array, which we set to be empty. Now we have the data available from Firebase, which includes any labels which have already been selected. We can now update this array to include any cards which you currently saved. We can use this as soon as the component mounts. We have component did mount and then inside here, we're simply going to set the state with this. set state. Our object is going to update the selected labels with value from our props, which is stored in card data and the card data wants is the labels field. Now let's save this and open up the modal and see what we need to do. Go to the project, click on the text. The first thing to do is to add the card text inside of this text area. The user can change it if they would like. The second thing to do is to loop through our selected labels, and then display them just under here. Let's start by adding in the card title into the text area. Back open to VS Code, we can go down to the random effort and take a look for the input, which is just down here as our data is onto the online. We need to add the default value which is going to display the value of the text. We can set this from props. So this. props. card data. text. The second thing to do was to loop through all of the available labels in state and then display them under this labels title. We already have a place holder comments where we want this to appear. But now I want to replace this by mapping through our selected labels. Inside the curly braces, we can select our states, the selected labels. I'm going to use the map method to loop through each one, store each value inside of a label. We can then set up our function for each one. Inside here, all we're going to do is to return a HTML span element. This span element is going to have a background color, which is the same as the label color. Inside the opening tag, we can create a class name of label. But also we want to set the style value with a double curly braces. Set the CSS background property to be equal to the label. This background-color of label is going to be equal to the hex value which we have inside the state. This selected labels will contain any of these hexagon values. Then scrolling down, we can set these to be the background color for our span. Since we're looping through, we also need to add a unique key to each one of these span elements. Just after the background, we can also add to the key, which is going to be equal to our label. This is going to be fine to use since each one of the six colors is unique, meaning we won't have any duplicates. So save this, and then over to the browser. Let's now go into any one of these modals by clicking on the text. We see the text inside here with a value of one. Let's try number three. We still don't have any labels available for these cards to display, but we see the value of three is now in a text inputs. To enable us now to edit this card, we can add a new method onto the form when we submit. Let's go back over to our modal and then scroll up to the form. Inside the opening tag, we can add a on submit, which is going to be equal to this.update card. Just before we go ahead and create this update card method, I'm going to add a ref to the text input to first grab the value. Scroll back down to the input with the class of textbooks edits, which is just here, just after default value. We can also add a reference with this. text inputs. Now above, we need to create this ref and also the update card method. Just below component did mount. We can create our ref, which was text inputs and that is equal to react.create ref. After this, we need to create our update card method. At the moment, this method is going to concentrate on updating the text. We will come back to the labels very soon. Let's start by making this async function, which takes in the event information such as the arrow function where we add the trial section, the cut section just below, which we're going to pass in the error and then a console error that detects all error updating card. Add a colon, and then pass in the error. Inside of our trial section, we're going to first call prevent default on the events. To stop the default behavior of the browser reload in. Next open let's create three constants. We need to grab the ID of the card, we need to grab the new text which has been added into the input field and then we need to grab the current card from Firebase. Lets start with the card ID, which will have available inside the props. Card data.id. The next one is for the new text which you stored inside of this ref. So const new text. This is going to be equal to our ref value of this.text inputs. We can grab the value with dot currents dot value. If that constant we need is for the current card from Firebase, we're going to wait its information to come back, which is from our cards ref.doc and then we can pass in our card ID. Now we have the card from Firebase, we can call the update method. Inside here, we set up our objects. For now the only field which we are going to update is the text. I will grab this from card.text, saying is equal to our new texts constant. Just after our updates, we can then close our modal by calling the toggle modal method, which is available from props. So this.props.toggle modal. As soon as the card is being updated and the form is being submitted, we'll then close down the modal, and return to the board view. Just before we continue, make sure the cards ref is imported at the top of this file and also make sure this is ID. Let's give this a Save and go over to the project. Select any of these cards. Take the modal, and change the value inside of the text inputs. It now save the changes and now toggles the modal to be closed. If we go over to the console, reload this into the cards collection. Now we can check our card number one has been changed to 100. Inside of our project, we still need to refresh to see the changes until we add our real-time functionality later. This is all going into now due to update the context. In the next video, we will concentrate on updating the labels.
30. Setting the labels: Updates in the labels inside of our card components will involve a little bit more work than in the last video where we updated the text. This is because we will be toggling the labels on and off. When a label is clicked, we first need to check if the label needs to be added or removed. To do this, I'm going to add a in line click handler inside of our model. When the edit card model, in this section we created in the last video where we loop through all the available labels. We can also add an on-click event handler. This is going to be an inline arrow function, which is going to call a method called this dot set Lebel. Also passing in the current label value. As soon as the user clicks on any of these labels, it's n going to trigger this set label method, which we can now create outside of our random method. So set Label, which takes in the label which is passed to it, sets up our arrow function. The first step inside here is to create a constant which is going to be called labels. This is going to store as an array all of the currently selected labels, which is stored in the states. We're going spread these in with this dot state, dot selected Labels. The next step is to check if this passed in label is currently stored inside of this array. Let's do this by creating a if - statement. We can check if labels, dots includes, which is a JavaScript method taken in the current label, open up the code eraces. If this passed in label is stored inside of our labels array with M12 call the filter method to remove it. We can store this inside of a new array called new labels. We can grab our current array called labels, called the JavaScript filter method. Then we can store each value inside here into a variable called elements. That's about function, it's a run for each one, which is going to return any elements which is not equal to our label. We can then update our state with this dot set state, where we are going to obtain the selected labels to be equal to our new array. This is what's happening if the label is included in the array. If it isn't, we're then going to add a L section, which is going to push the new label into state. So we have the labels. We can then call the JavaScript push method, which is going to push the new label to our array. We can then update the state. Once again, updating the selected labels with the value of our labels, array. So just to recap what we are doing here, we have the selected labels stored into states which would then taken a copy of and saved known to this constant. We then check and if the label which the user has clicked on is stored inside this array. If it is, we're going to go ahead and run this section of code, which is going to be responsible for filtering out the current label, and install on the rest of the values into this new labels array. We'll then finally push this to state once the label has been removed. If the label which is being clicked on is not stored inside the states, we then run this l section which is just below. Instead, this is going to push our new label to our array and then save this state. Now, we can go back to our update card method, which is just above. We can update this to add our labels. Just after the new text, we can create a constant call labels and set this equal to the value stored in state. This dot state dot selected labels. We can also push this to Firebase inside our update method. We can also select the card dots, labels fields, and set this equal to o labels. So save this and let's go over to the modal. Click on any of these, and then select label. We currently don't have this interstate. So it's added. If we click on it again, it will then remove this from states by calling the filter method. Let's see if any of these are up here in your Firebase, we can click on these to save the changes. Then we load our cards. This card 100 is now being updated with our two colors. Before we go any further, this modal component is also receiving props. So we can add some prop validation. So as ever, we can import the prop types from our module, which is called prop types. So this card modal is receiving three different props. If we take look into card that dropped a yes. We have the modal open, we have toggle modal and also the card data. So back down to the very bottom of the modal. We can set up our prop validation. So edit Card model. The prop types, lowercase b, setup our objects. The first one is going to be modal open, which is going to be equal to prop types. This is a Boolean value so we can select w, this is also required. The second one is toggle modal. This prop type is a function so we add that func. This is also required. A third and final is our card data. The prop type is an object which is also required too once we set the Prop types. The final piece of this video will be to display inside of our application the selected labels just above the context. For this, we need to create a loop inside of the card.js. Remember inside of this card components, if we open up the react developer tools, if we search for the card, this is where we store all of our current data inside of this Dataproc. Inside here we have the labels which we're going to loop through for each card. So up at the top of our render, just underneath the class of card, we're going to create a new div, which is going to be a new section that contains all these labels. The class name is going to be equal to card labels. Open up the card eraces. We can access our props and the data dot labels. To be approved and we can use the map method, which takes in the label. So it's above arrow function. Then it's going to return a span elements for each one. We can pass in our key, which can simply be the value of each label, the style. So we have the color value, we can set the background color to be also equal to our label. Then finally, we can ask a class name to this, which is going to be label. Good. Now, I'll give this file a save and then go over to the browser. We can instantly see that the two colors which were added as being updated in the card components. Let's try to move in the blue color and add in a green and save the changes, refresh. This is now reflected inside of the card components. So all of the updating features are now complete. I will see you next where we will improve on this card by allowing multiple lines of text.
31. Text area auto resize: If we click on any of our cards and open up the edit modal, this is currently a text input, which will only allow us to add texts onto one single line. It will be better if our cards could have multi-line text, and the card would expand to fit each line. To do this I'm going to add a package called react-autosize-textarea, which will allow us to add these to project. This will give us a textarea, which will also resize the height of the card, based on the number of lines of text. Let's go over to VS code and add this to our project. Down at the bottom. I'm going to close down server with Control C, and then we can run and npm i react- autosize- textarea. Then let's run this-
32. First look at onSnapshot: Each time we add updates or remove anything from our projects, we need to do a refresh to get the new data. Well, this is true for most things, if we were to go ahead and add a new board, let's say, courses to take, add the color and then create a new board, you'll see this will appear without a refresh. I wanted to show you two different ways we can approach updating this application. The first is just as we have here with the new boards, each time we add or remove a board, we set the boards into state. As we already know, one of the benefits of this is, it will update all the components which we'll use as state. It is also going to be generally faster than waiting on the database to send the data back, but this also means we have two sources of the same data. We have the board stored in state and also in Firebase. If an error occurs when updating either one of these, it can then cause our application to be out-of-sync. Another approach which we're now going to use our lists and cards is to use Firebase's real-time functionality to tell us when something has changed. Rather than us asking for the data, Firebase will send it to us each time there is a change. Let's begin with the get list method in the board components. Go to the board.js and scroll up to get lists. This is here just about the top of this file. Get lists uses this get method to get what is called a snapshot of our data at the current time. To get real-time updates, we can replace this with a method called on snapshots. On snapshots, it touches a listener which will notify us when a change has been made. To do this, I'm going to comment out our existing data. So everything just above our catch block, all the way over to the get method. Now we can begin to replace this with our own snapshot method. The same principles do apply. We want to get our data loop through it, create a list object, and then save it to state. First we call on snapshot, which takes in a function. Just in the auto by, we can then call on snapshots, passing in the snapshots for each function. For each data, snapshots, which is an object containing details about query, we then want to call a method called doc changes, so snapshots.doc changes. Doc changes will return an array containing the changes since our last snapshots. Then what do we need to do when we have an array of data? Well, we need to live through it so we can work with each individual item. Just after here, we can then call for each, passing a callback function, so for each change. But I'm going to run the code inside these braces. Before we go any further though, let's do a console log and we can log the value of change. Save this file. Go over to the browser, open up the console, click on any of these boards, and let's add a new list. Let's say, to do list one, hit enter, and we'll get a console log. One thing we need to note here is this type of added. Bear this in mind as we will need comeback to this very soon, but the main thing here we need is this doc. This is a snapshot of the documents containing all the data which we need. We can see it has the ID. If we click on this and we can grab this with doc.id. Something which is not so obvious by looking at this doc is how we get the rest of our list data. How we can in fact get is by calling a data method. Let's go over to our console log. We can access our doc which we've just seen in the console and then the data method, save this. We now see inside here, we have our list object which contains the board ID, the created at date, and also the title. This combined with the ID we seem for, will now give us all the information we needed to construct our new list. Let's go back over, we can remove our console log. Then inside of our four each, we can create a constant called doc. This is going to store the value of change.doc, giving us a reference to our documents. The next step is to create our list, which is going to be an object. We first need to grab the ID, which is available from doc.ID, which is exactly what we seen before, so doc is equal to change.doc.ID. We then need to grab the title, which is available from doc, the data method which we just looked at. Grab our list objects, and then grab the title outside of our list object. We can then set the state, so this.setstates passing in the objects. The state we want to update is the current list. As an array, we're going to merge in the current list, so this.date.currentlists then separated by a comma, we can add in our new list. Now save this file, and we can go back over to our project in the browser. We can try and add a new list, and this should be added automatically. Let's say to do list two, hit enter. Now this is being updated without needing to refresh the browser. However, though, if we now click on any of these lists and delete, we now see a error inside the console and also our list has been added as a third item. The error message down in the console says that it's encountered two children with the same key. This is because of the way we handle our document changes and this is what we'll look at in the upcoming video.
33. Working with document changes: In the last video we discussed was an era when we removed one of our lifts. We've got the message I've encountered to children with the same key and then we've seen an extra list appear inside of our project. This is because of the way we have things at the moment in our own snapshot method. If we go over to the board dot.js, where we were working on our last video and then into the get list method. We are always constructing a new list item and then setting the state, which is this section just here. Even if the item was removed, we still get the change data from the list we then add it to our object. Then set it to states, this will result in the group of items which you see here. Therefore encounter in it two children with the same key to pixels. If you remember from the last video, we said to bear in mind when we did the console log, there was a type of added. We can use this to either set the state or to remove the item from state, depending on if the list was added or removed and we can do this with a if statement. Let's go back to our board.js. Then it just above where we construct our documents. We can add an if statement to check if the change.type is it equal to the string of added. If it was, we can open and close the curly braces. We can then grab all of our data from set states, our list and our documents. Then add these inside of our if statement. Now this will only set our state if the item has been added. However, if the item has been removed, just undo our if statement, we can then add a second if statement, bracket the change.type. This time is equal to remove. If it is, we can then open up the curly braces and then we can once more set the state, sets up our state objects. The state we want to obtain is the current lists. Sets of our array and now since we are removing an item from state, we can use the JavaScript filter method. We can do this by merging into our array a copy of the current lists. Merge these in with the three dots,.state,.current lists. We can then call the filter method. Inside of this filter method, we're going to run a function for each item inside of our list. We want to return only the lists where the list.id is not equal to Change dot doc, dot ID. Just to recap what we are doing here, we are grabbing all of our lists from states and then we're going to only return our lists where the id for each particular list doesn't match the one which has been removed. This is available from change.doc.id. Now all that's left to do is to save this and go over to the browser. Inside of our board, we can add a new list. Lets say to-do list three add this in. We're going to move any of these and now these are added and removed without causing any errors. Finally, from the last video, we still have the commented out section where we use the guess method. We can now safely remove this since we won't need this code anymore. This is our list now working with Firebase real-time data. Next, we will also apply this to our cards.
34. Realtime cards with updates: We can also add this on snapshot listener total cards too. Meaning if we cause any updates, if we add any cards or delete any, these changes are immediately reflected in the app. Let's do this over in the.js, which is responsible for fetching the cards with the fetch cards method. Let's scroll down to fetch cards. Just like with the list we're going to comment out everything from adjustable catch all the way up to the get method. Then we can now replace this with our snapshot. Just have to order by we can add on snapshot which then takes in a snapshots of each change. So it's about function, and then inside here we're going to live through each one of the document changes. We can do this with snapshot.docChanges. For each document change, we're going to run the forEach method passing in the change. We're going to construct our card just like we did with the list. First of all, create a constant called doc, which is going to be equal to change.doc We then create our card set of all card objects. The ID, remember is from the doc.id separated by a comma. We also have the text which is available in our doc variable. We have the data method to grab all the data. The data we want is from the card object and the field of text. This one also has the labels too. Just like the line above, we call data accessible card object, and then the field called labels. Then just like we did in the last video, we need to track the change type. Then set the state depending on if it was added, removed, or also modified. Let's do this. Just after our card objects, we can add a if statement to check if the change.type is first equal to added add the curly braces. Then we can set the state, so this.setState. Since this is an addition, we're going to merge in the current cards as an array for the spread operator, grab this.state. This.states.currentCards separated by a comma we're then going to merge in our card objects. Underneath this first if section, we can add a second one to check if the change type, this time is going to be equal to removed. If this is removed, we are going to do a very similar thing to the lists where we are going to filter out by the id. We're going to first set this.setStates, passing our objects, select the currentCards. We're then going to spread this.state.currentCards where we are going to call the filter method. Each item will be stored inside of this card variable, we'll then only going to return the cards where the ID doesn't match the one which has been removed. The card.id which is not equal to change.doc.id,. After this removed section, we're then also going to add a modified section. This time if the change.type is equal to the string of modified, we then run this code inside of the curly braces. The first thing we need to do is grab the index number of the item which is stored in the states. We can start this inside of a constant called index. This is equal to this.state.currentCards. We're then going to use the find index method. Inside of here each item which will loop through, it's going to be stored in this item variable. Therefore, we can only return the item where the item.id is equal to change.doc.id. This is going to return a single item from our currentCards. The item where the item ID is equal to the one which is being changed. We need this index number, all this position of our item inside this state so we know exactly which item to update. The next step is to create a constant called cards which is going to be equal to all the cards in our current state. We going to grab these with the spread operator so this.state.currentCards. We now have everything we now need to update our state. We have the currentCards which has been modified. We have the index number which is the position which is stored in states. We have all of our rights come from states, so now we can go ahead and update this. First, we select all our cards in states. We select by the index number, the individual card which we want to update. For example, this would be cards zero, cards five, cards 10, all whichever number this is in our state. We're then going to replace this with our card object from above. Then set this to state with this.setState pass in our objects, so the current cards is now going to be equal to this cards array. We can now scroll down, and remove the original code, so with the get method, and also the for each. Also if we scroll back up, we can now see we're no longer using this current constant. We can also remove this and just simply awaits our cardsRef. We'll save this file and now we'll go to the browser and test this out, head over to the board. I will need to add some lists add as ABC. I can also add some more into our different lists. We can add cards and this updated in real time. Let's try to move in number two that's good, and number four, if reload, these are still showing. Let's now try to modify this. Let's change one to be a hundred. Save our changes and this changes are now being reflected in real-time. This now leaves us with our board listing cards, all now updating without need to refresh the browser.
35. React Context API: As ab become large and more complex, we often need a better way to manage our states. Passing props down many levels which is often referred to as prop drilling can add a layer of complexity. This is where state management libraries such as Redux have played a part to help manage this. Redux is fine, but it also means learning new things, add into our ab's overall size, and it can also add complexity if we were only using it to pass around state. A solution to use the React Context API. Context was created to share data that we need in multiple parts of our app. In this section, we're going to be using Firebase to provide user authentication. Users can log in and sign up, and then only see the boards which they have created. This would be a good use case for the Context API since the logged in state is needed on multiple pages. When using Context, we no longer needs pass down data, in our case, the logged in states from the parent component through the child components. Instead, we basically have a component with global state, which we can import directly into any other components so we can access the data. The first thing you might be thinking is, "Why not just move all of our states into this Context?" This is a good question. While this is certainly possible, the creators of React do discourage this since it can make components less reusable, and passing down props only a few levels, can be a much simpler solution. Over in the Components Directory, let's create a new file for our Context. In the Components, New file, I'm going to call this the AuthContext.js. This filename is up to us but I have name this the AuthContext since it will handle the user authentication. Up at the top of the file, the first thing we do as ever is to import React from React. This React package will allow us to access the Create context method, which we can now store in a constant called AuthContext, so that is equal to React.createContext with the brackets just afterwards. So now we have this context object. We can create two things. We need both a provider component and also a consumer. As both of these sound, the provider will provide the data to other components, and the consumer will get the data and also be subscribed to any changes. First, we can create the provider component, just as we would with any normal React components. We can create a class called AuthProvider, which extends React.Components. Since this provider is responsible for providing data, we can also add in any state. So let's set up our states object where we are going to set the initial user to be an empty object. We also need to pass in a random method too, just as we normally would. Inside here, we're going to return some JSX data in between the brackets. However, this is not going to render out JSX like we've done previously. Instead, we're going to return a context provider component, which looks like this. So we can grab the AuthContext, AuthContext is the variable which we set just above, then we're to access the Provider with a capital P, close this off. This component will allow other components to subscribe to any data changes. Inside of the opening tag, it takes in a value, and this value can be anything which won't pass over components. I'm going to use it to pass down the user from states, which we just set before. Inside this opening tag, we can set the value inside the double curly braces. The value name of user who's going to be equal to this.state.user. Down at the very bottom, we have all we can use this in our components, we also need to export this provider. Inside the curly braces, we can export our AuthProvider. So I've added this as a named export inside these curly braces since we'll also export a consumer very soon. So now we can take this provider and also the data, which is the user, and make it available to the rest of our application over in the app.js. Inside here, we can first import this provider at the very top. Import inside the curly braces, our AuthProvider. The file path is going to be equal to.slash, this is in the components folder, and the name of AuthContext. The way we make this data available to all components is by using this as a wrapper component. Let's go down to our browser router, and then we can add this inside here. So up at the top, the browser router. We can add this just like a normal component. This is the name of provider. This has an opening and closing tag, so we can take the closing tag and wrap all of the content inside of this provider. To take this down, just above the browser router at this end, and then save this. If we now go over to our application, and if we do a refresh, we don't see any content on the screen. This is because since we've now used this AuthProvider as a wrapper, all the components which are now inside are now a child of this components. So let's take a look at what is going on over in the AuthContext. Inside here we have this AuthContext.Provider, which will provide any value to all of the child components. This component has no content in between the opening and closing tags, and this is why we don't see any content on the screen. So how do we tell React this component should also render out all of the components which are nested inside the app.js? Well, we can do this with this.props.children, which we can add inside the curly braces. Now give this file a save, and then over to the browser. We can now see all of the components are working as expected. This now leaves us providing the content to other components. So we can now set up the consumer which will go ahead and use this data. In the AuthContext is where we are going to be setting this up. Let's do this at the bottom, just after our class. So the first thing to do is to create a constant called AuthConsumer. We're again going to use the AuthContext, which we set up at the top here but this time we're going to grab consumer rather than provider, which we used before. So AuthContext.Consumer, and then the second thing to do is to add this AuthConsumer to our export so it's available to use in other files. So just before we go and test this is working in other components, let's add some initial data to work with. At the moment, we've got a blank user object. Let's simply add a name inside here, so we can test the data is reaching the components. So now save this. In the app.js, we'll now provide in this data to all of our child components using this provider. So now we can go into any of these components nested inside and then take advantage of the consumer which we created to access this information. Let's do this Auth in the board component. The first thing we need to do up at the top is to import our AuthConsumer from our file name which is./AuthContext, scroll down to the render. We then use this AuthConsumer as a wrapper to all of our content. So just under return, we can add in our AuthConsumer. Close this off. Let's grab this, cut this out of place and add this right at the very bottom of our content. This AuthConsumer component lets us subscribe to any changes inside the context. So if a user was updated in our AuthContext file, this would then be passed down to this consumer. Each time there is a change, this AuthConsumer takes in a function as a child. So let's start by cutting out all of the data inside the AuthConsumer. Cut this out of place, I'm going to add this back here in just a moment. Then we can pass in a function inside of the curly braces. So open up the brackets, set up the arrow function. This function takes in any value which is being passed in from the Context. So currently inside of the provider, we're only passing in the user value, so back over here in the consumer, we can pass in the user inside the curly braces, and then inside of this function body, we can now paste in the content which we had before. So add this in, and now all of the values which you passed in to the function should now be available inside this code. We can test this is working by outputting this user anywhere inside here. Let's do this just above the board header, inside the curly braces, we can output the user and then access the name from our object, save this file, over to the browser, and now we see the name which had been provided from our state. So we will make use of this data inside this consumer in just a while, but for now I'm going to remove this name since this is all now working. So just as a quick recap, we are creating a context file, which is going to store our user into states. We're going to be grabbing this user soon from Firebase, but for now we've hard-coded in a value just below. We've then set up our AuthContext, which has then got a provider and a consumer. The provider is responsible for passing down data to any child components. Currently the only value which we're passing down is this user object, we then create a consumer which then takes in the data inside of any component which needs it, then over in the app.js, we imported the provider and then wrapped our whole application with this. So all of the child components have access to this data in the board.js. We then use the consumer which we created, which then has a child as a function, and then pass down this user into our code so it's available to use anywhere which we like. As you can see, there is a little setup required with Context. This is why it is recommended to maybe only use, if passing down props, multiple levels. However, though, once this setup is done, we can now access this data just by adding in a consumer to any components which will need it. Next, we'll begin to look at using Firebase authentication to allow users to sign up and login. We will use this logged in states and then pass it down to any components which needs it via Context.
36. Firebase Authentication and set up: We will be using this context API we looked at in the last video, plus the currently logged-in user to different components. We will be doing this with the Firebase authentication package, which will have the ability for users to sign-up and login, and it will also listen for any changes and then update our state. For example, when a user logs out, state will then be updated and this will then let us hide any information which they shouldn't see. Another benefit of having a logged-in user is we can also use the user's unique ID when creating a new list board account. This means we can then filter the data which we get back from Firebase to only show the items created by the logged in user. Also the Firebase console, we've currently been using this database link, but we can set up the authentication just to both. Go to the sign-up method, which is this button just here. Firebase provides us with lots of different ways which we can sign in users. We have options to use social media, such as Facebook or Twitter, but the one I'm going to add is an email and password combination. Let's go up to this at the top, click on here, enable this, and then we can save using this button here. The next thing to do is to go to our Firebase Config inside of our projects, which is the Firebase.js, and then inside here we can also import the Auth package just like we did above with firestore, so import from Firebase, the auth package. Then below the configuration I'm going to add a shortcut to the off method and then store it inside of a constant. Below of database, I'm going to call this constant, the firebaseAuth, and set this equal to firebase and then the Auth method. We can then import this reference into each file which needs it and then access the authentication methods provided by Firebase. To do this we also need to export this, go down at the bottom as I named exports, we can add firebaseAuth. To create a new user, we also need a form, so we'll create a new component for this inside of the Components folder. Let's create a new file called the UserForm.js. Close down the sidebar. We can then import React from reacts, inside of a class-based components called the UserForm, which extends React.Component. I'm going to set up two different methods, which is going to be for the email and password so we can drop the data which the user has entered. The first one is reference to our email input, and then we can create our ref, just like we've done in previous videos. We want to duplicate this and then change this to be the password, and create our render method which we are going to return our form. We can surround this with a React Fragments. Then inside we can add our div, which is going to have a class name for our CSS called sign-up-wrapper. At the top, we're going to add a level two heading, which is going to be the text of sign in or create account. Then our form, which has the two inputs. Remember From here we use in the email and password combination, so we need to add these to our form. Let's create a form with a class name of sign-up form. We can add a div which is going to surround each input. The first input is going to be for our email and we can attach our ref, which we created just above, which is equal to this dot email input. On the next line. This has a type of email. Also, a name which is going to be equal to email, and then a placeholder of email too. Then our second div just below. Let's grab this section here, copy this in, and we can change this to be the password, so the input is going to have a ref of password input, the type of password, the name of password, and also the placeholder too. Just after this div, we can also add a button. Let's create a wrapper div, then a button. Then inside here the text of sign-up. Finally down at the bottom, let's not forget to exploit this with an export defaults with the name of UserForm. The sign-up form will be the initial components a user will see when they first visit our application. We can add it inside of the router on the home route or in the app.js. Let's first import these components at the very top. This is called the UserForm, which is available from./Components, and then you use a form. We can add this below down in our router. Currently if we scroll through all of our routes, we don't have a forward slash route for the home, so we can add this right at the very top. We can create a new route. We can set this to be exact with the file path from home route, or the forward slash. Then the components which we want to render out is this UserForm. Also the browser, we can now test this out, if you go to our project and then go to forward slash, we now see the UserForm components. We now have this user form at the root of our projects. In the next video, we will make use of this form to allow us to push a new user to Firebase.
37. User sign up: I will use a form is now ready to be wired up to a method to push a new user to Firebase. Since we're using the context API to hold all of our user data, I'm going to set this up over in there. Let's go over to all contexts dot JS. Then at the very top, we need to first impulse our reference to the firebaseAuth package. This is a named export, we do this inside of the curly braces. The firebaseAuth from Firebase package, which is dot-dot slash and then Firebase, then we can create a sign-up method which will make use of the email and password, which will be entered into the form soon. Now down in our class, just below our state's objects, we can create a sign-up, which will be a sync taken in the email and also the password and then finally the event information. Inside here we can create a try section and we can also catch any errors. Rather than outputting a console log we won't come back to this very soon. We'll add a hand lens soon. Just above the first thing we're going to do is to grab the inventive mission and then prevent the default behavior. We can then make use of this firebaseAuth package which leads to [inaudible] both. We're going to wait, firebaseAuth and then we can call a Firebase method which is called CREATE_USER with email and password. Inside of the brackets, this takes in the email and password, which is going to be passed to our method and this is all we need to do now for the sign-up method. The next thing to do now have this available inside this file is that these two are provider as a value. Just below the user, as are these onto its own line. Add a comma, now we can also pass down our sign-up method, which is equal to this dot sign-up, just exactly as we would do when passing down prompts. The sign-up method can now be accessed throughout the context API. Let's go to a user form dot JS. I'm working now import this Authconsumer at the very top. Inside the curly braces, you have Authconsumer from our package name which is at the file path of dot slash and then the AuthContext. Just like we did with the bold components, we need to surround all of our content in this consumer so let's go down and grab everything from this return section. We can cut this out and in need of consumer. Remember from the last video we said that the consumer needs to have a function as a child. We can add this just inside the curly braces instead of a function and then inside of here we're going to pass in the sign-up method inside the curly braces. Then inside this function body we can paste in all the contents which we just removed. With this now as a wrapper, all of these contents now has access to the sign-up method. This can be placed in the button as a on click handler. Inside the opening tag, we can add on click creates a in line function which takes in the event information. This is going to ruin our sign-up method and remember this takes in the email and password. The e-mail is available from this dots email input, which is our REF dot current dot value. Separated by comma, we can do the same for the password. The REF was called password inputs and then grab the current value. Also, remember when we set this up in the context, if we scroll up, this also takes in the event information. We can pass this in as a third argument. Let's now save this file and test this over in the browser. Let's create an e-mail inside here. Then we also need to add a password which is a minimum of six characters. Click on sign-up. Home to Firebase. Click on the user's tab and now we'll see our one and only user which we just created. If you don't see any users applying inside of here, do go back through and check the code and also make sure that the password is minimum of six characters long. Otherwise, you will see an error inside the console. If you are seeing users in this Firebase console law, you are now good to move on to the next video where we're going to look at how a registered user can log in and out.
38. Logging in and out: Once a user has signed up, they also need to login and out. We also going to do this in the off context as custom methods, starting with the login. Let's allow it to the off context.js file. Then inside here under the sign-up, we create a new method, it's going to be called login, it's going to be a sync, also taking in the e-mail and password, along with the event information, which we're going to pass when calling this, as at the try section, and then just like the sign-up section above, we're going to pass in any errors, but we'll deal with this section very soon. Inside the try section, we're first going to use this event information to prevent the default behavior, and then we going to wait, our firebase off and then we can use the firebase authentication method called sign-in with email and password, all camel-case. Sign-in with e-mail and password, and then inside here, just like with the sign-up, this takes in an e-mail, and also the password and the sign up form. Just below this, we can do a test to check if this is working with a console log, with the text of logged in, and we'll come back to testing these in just a moment. Logout, we're going to add the log-out method, suitable function, the try section, the cut section just afterwards, as an in the error, we'll come back to this soon. All we need to do in the try section, is to access the firebase off, and then call a method called sign-out. Once this is done, we can then update the state with this dot setState, [inaudible] of objects, and the state we want to obtain is the user. I'm going to set this back to a empty objects. Again for testing, we can add a console log, which will output a string of sign-out, down to the provider. We also need to provide these two methods, so these can be accessed inside of other components, so as a value we have login, which is equal to this dot login, and then also separated by a comma, we have logout, over in the use of form components, we can then press in the login method to the consumer. Just have to sign-up, we can also add login, we can also add in the user, and now this means we can now trigger this login method inside of these components, and we're going to do this by adding in a button just above the sign-up. Let's scroll down to the sign-up button, and then just above this, we can also add a new button, which is going to be for logging in. Just like the sign-up below this is going to pass in a onclick event handler, which is going to trigger a method. We're going to pass in our events. I denote an inline arrow function, with the method name of login. The login needs access to the email input, and also the password input, just like we have below, along with the event information. I'm going to copy these three lines, paste these in, and in between the button tags, we going to add the text of login. Save this, and then go to the browser, into our projects, we now see a login button. Let's open up the console. We can now then our e-mail and password combination, and then we sign-up with. Before we click on login, let's change this to be a wrong e-mail. Click on login. We see an error message down in the console. Let's try a different password, login. We also get a second error. Now we can answer the correct sign up information, click login, and then we've get our console log of logged in. We will come back to these error messages very soon. To be more clear to the user, what's gone wrong. The next thing I'm going to do, is to create a header component, which is going to display the current logged in user, and this will also be where we can add a logout button. Let's create the header component now. Inside the sidebar, under components, we can create our header.js. As ever, we import react from reacts. We're also going to use the off consumer, so I'm going import this. This will give us access to the user's login information, which we can access from a law of context. We don't need to create a class-based components, since this is going to simply take in some information, and then render it to the screen. Let's set up a function based components. We can ad the HTML header elements inside here, as a wrapper, the authconsumer pass in the child, which is going to be a function inside the curly braces, this takes in the user, and also the logout method, set-up our arrow function. The brackets, as a wrapper we can pass in the react fragments. Let's begin at the top left of our application. We're going to add a home button, which is going to be a home emoji, where the user can click on and be redirected to our homepage. Let's have a element, since this will be a link, the href is going to be equal to forward slash. Then inside of the span elements we're going to have a HTML entity, which is the ampersands. The hash, then the value of 127968, the semicolon. Respond can also have a role, which is equal to image, and then for accessibility you can add a label, which is going to be equal to house emoji. Alongside this, we can add a level one heading, which is going to be for the project name of [inaudible]. Now over on the right-hand side of this header, we're going to add a section which is for the user area. We're going to use the context to display the user's email when logged in. A button to log-out, and also the text of please sign in, which we're going to conditionally render when the user is not logged in. Let's start with the small elements. We're going to display the user, and then we're going to output the user dot e-mail, which we're going to grab it from context. After this, a button, which is going to have a onclick event handler, and this is going to take in the event information, and then run our logout function, and then inside of here we can pass in e, to in ease thanks, we can also add the text of logout, and then the third thing we're going to add into here, in between the small elements, is going to be the text of please sign-in. Very similar groups together, the button and the user, and will only display these when the user is logged in. When the user is logged out, these will both be removed, and then will only output the text of please sign in. Save this file, and now we can import this in our app.js. Right at the very top, at import our header from the file path, which is dot slash components, and then the header. This component will always show on our application, therefore we need to add this outside of the routers switch components, so just go switch add any header, closes off, save this and now reload the browser. I may also need to export default inside the header. Let's go there now, right at the bottom, so export default, and the name of header. Let's try this once more. Now we have the header showing inside the application. We can now try logging in, using the correct information. We get the message of logged in. Let's try the logout button, and I will get the message of signed out. In the next video, we'll be using another Firebase method, to listen out for when a user logs in or out, and then obtain the state with the current user.
39. Listening for auth changes: When a user logs in and out of our application, we need a way to track this and update the state. Firebase provides us with a method for this called onAuthStateChanged. This will listen to any changes to our uses of status, and then we can update our own state. Doing this will allow us to protect certain views in our app, such as the board's view if the user logs out. We can't attach this listener once the components mounts in the auth context. Let's head over to the file of context.js, and then we can add this in a life cycle method called component will mount. Inside here we're going to access a method which is going to be called onAuthStateChanged. Inside here we're going to setup a function which takes in the user. If the AuthStateChanged has cause the user to log in, the user value will be stored inside of this variable. We're going to first check if the user is present i.e, if they have logged in. We'll then going to update the state with the current user value, with this.set.State. Passing in our state objects, where we're going to update the user. Our user object is going to contain a id, which is going to be equal to the user.id. We also need to grab the email, which is from the user.email. This code will be triggered if the user has logged in on the else user information if not, we're going to add a else section, which is also going to update the state to be an empty object. Then we set the user to be our empty object, just like this, and we have an error message down here, so FirebaseAuth just like this, and we can also change our state just above to be an empty object. Since we now allowing Firebase to control this. Below this, we already providing this user data to over components down as the value. I scroll down, we have the user, and also in the header components. If we take a look here, we also imported this user just here, and then grabbing the user's email just below. Now let's go over to our projects and we can test this. Let's try logging out. We see the message of signed out. Let's try logging in. Good to not only do we get the logged in message in the console, we also see the user has now been entered into the header. Let's try logging out. On the header is also updated. Good, this is all now working, but now we just need to move this over to the right-hand side. To do this, let's go to the header.js. We can cut out all the user information. We can create a div as a rapper, [inaudible] back in, and then add a class name. Activate the CSS, which is going to be equal to user area. Save this, and this now pushes our user area to the right hand side. Good, so we now detecting that the user's logged in state, and in the next video, we can use this for conditional rendering.
40. Conditional rendering: Now that our app is where if the user is logged in, we can use this information to do certain things. One of them is to add conditional rendering, which will allow us to do things such as only displaying a board if it was created by the current logged in user. Just to begin here inside of the ball view, we output in a sign-in components. This is because over in the app.js, we have a mistake just here, so I'm going to save this just before we go any further. Now this is in place. We can go to the board.js, and we can add some conditional rendering for the board components. To begin, I'm going to add a new property to state, which is going to be a empty message to begin with, and then we can update this message when we can't find a board or the board has been removed. Let's go down to our get board method, which is just below this. Inside here, we're trying to find a board by the ID. If no board can be found rather than the console log, we can update our message in state. This.setState inside of objects, the property which we want to update is the message, which is simply going to be a string of board not found. We can also copy the set state section, and we can also add this tableau when we also delete the board too. If we save this file and now go over to any one of our boards, such as this board components here, when a board has been removed or cannot be found, we need to hide the board title, the delete button, and also the new list at the bottom. We can do this in the board components by adding a ternary operator based off if we have a message inside a state. Let's go over to the ball components, scroll down to our render, and then just above our board header, we can add our ternary operator inside the curly braces. We can check this.state. That message is equal to an empty string, we can then set up our ternary operator, which looks like this and this is just regular JavaScript. If this is true, and we'll just have a empty string inside the states, we can then rent out the header in this first set of brackets. Let's do this by cutting out the closing bracket right to the end, scroll down to just after the board header, which is this section here. We can then paste this inside, meaning that's our board header with the delete board button, and also, the text is now inside this first set of brackets, if this is false and we do have a board "Not_found" message, we can then output this message inside the second set of brackets, inside of a hedge to elements. The message is available with this.state.message. Now obviously the browser, let's give this a test. We now see our board header section up at the top. If we try to delete this board, this now removes the title and also the button, leaving us with the message of Board not found. We still have this new list button at the bottom though, and we can hide this by setting the input type to be hidden when there is a message inside the state. Let's go back to the ball components to our create new list inputs. Instead of setting the type to be text, we can also add a JavaScript ternary operator inside the curly braces, we can do the same as above. We can check if the message inside the state is equal to an empty string. If is, we're going to set the input type to be text, if not, we'll set the input type to be hidden. Now let's Save this, for this current board which we just removed. This is now removed the input type. Let's go to a different board any of this is fine, and the new list inputs is still there now this complete board component. Also, all it needs to display if the logged in user actually owns it. In Firebase, if we go back over to our Console and into the Database, inside of our boards, we added a user ID down at the very bottom. This use of ABC123 is currently hard-coded when we create a new board. This now needs to be changed much the logged in user, and we can do this all in the Create board form. Let's head over to there, inside of our components, inside here, we need to access the current logged in user, and to the list we can wrap our components in the off consumer. Let's go up to the top, and then we can import this, the off consumer, which is going to be available from the file path of../components folder, and then the off context down to the return section. We can now wrap this in the off consumer, let's add the components. Remember as a child, we need to pass in the function which is going to take in the user, which has all the logged in user's information set about auto function. Then inside of here, we can cut out all of the rest of the content. Grabs the form, all the way down to the closing form tag, and then we can paste this inside of our function. Now we have this user available inside these components, we needs pass it to our handle submit method so we can add it to the board objects. Let's go down to our own submit method. We need to remove this.handleSubmit, and then so can pass arguments with this, we can use a inline function. Setup an arrow function, which you can call this.handleSubmit. Having this in line will now allow us to pass in the arguments inside the brackets, so we need the event information, and we also need to grab the user.ID, so it will look to handle submits. That's an argument we also now need parsing the userID. This userID can now be used inside of our board object, rather than this hard-coded value of ABC123. This user can also be added to the if statement below where we checking if the board or title and also the background exists. We can also add a third condition to also check if the board or user is available, before saving this to Firebase. Now, let's save this and go over to the browser. This will need to be logged in so we can grab our unique user ID. Let's add the e-mail and password, which we signed up with earlier. Once we'll end up signed in with our email about the top, we now need to go to the URL. If we go to our users inside a Firebase, we can grab our unique user ID. We can then use this open URL with forward slash paste this in, followed by a forward slash boards. We're then taken to the section where we can create a new board, and we're now logged in as the current user. Now let's create a board name. Let's go for our test in, change the color, create new boards. We'll see if we tried to make this new board, that nothing seems to happen. If we go over to the database and check inside here, we'll see our board is not being added inside here either. This is because of the way our user ID is stored inside the Firebase. Currently when you're checking if the board title, background and the user is there before we save this. Well, in fact the board dot user is not recognized. This is because if we go to our of context inside here, when the state is changed, will then update in our user objects, to have the ID and email. At the moment we're setting the ID to be the user dot ID but if we go to Firebase and into authentication, the user ID is actually stored in a field called UID. We need to now update this inside the context. To my Firebase. Save this over to our app. Let's try testing once more, change the color, create new boards. Now this has been added. Let's just check the user has been recognized inside of our database, inside our testing board, rather than the hard-coded value. Now we have our user ID. We can now take advantage of this user ID property on the board and check it matches the current logged-in user before rendering out all board components. Back on to our board dot js. Inside here we're going to add a ternary operator. Let's add this just above our board wrapper. Inside the curly braces. We can check if the user dot ID is equal to this dot state dot current boards dot user, says about two sets of brackets. We can then cut the end section, so we can wrap our board components and then we can add this in right at the very end. Just after our board wrapper, which is here, we can paste this in. Inside the L section we're just going to add a empty span since we don't need to render out any content. Also to keep react happy we can also wrap this inside of a fragments. Just inside of the user, we can add a react dot fragments. You open the tag, grab the closing tag. Then we can add this down at the bottom. Just after this curly brace. Now let's give this a save and go over to the browser, into our boards view. Remember that only testing was created with this current logged-in user. The rest all had a hard-coded board value. Now if we click on testing, they should now work. We try any leavers. We now see that we just get the empty span with no content rendered to the screen. As an extra test. I'm also going to test this in another browser with a different login user. Now let's go to our home component and register a second user. Let's sign up with a second email. For this, I'm going to open up Firefox or any other second browser is fine. We can copy our local host 3000 into Firefox. I'm going to now log in as the second user. This is one which we just created. Click login. Now as a second re-check inside of the original browser, I'm going to log in as the original user. Go over to our testing board, let's open this, so now if we copy the URL which had been created with this user of the Firefox, we can now paste this in, hit enter. We now see a blank screen because the user which is logged in doesn't much the user field inside all of our board. This is all working fine. Something else which we need a conditional rendering for is this header components. We want to group together the user of email and logout button and only show these when logged in. Once logged out, we then want to remove these and only show the text of please sign in. This will be straightforward since the header dot js component already has access to the user from the context. Let's go over to our header components. Inside here we have access to our user inside of the consumer so we can scroll down to our user email and also the button. We can surround these in a fragment. Close this off, take the closing tag and add this just after the button. We can then add a ternary operator to check if the user dot ID is present. If it is, we are going to run the code inside these first set of brackets. If not, the code inside the second set will be run. Grab the closing brackets, right to the ends cut this out, paste this in just after the end of our fragments. Then we can grab the small section of please sign in and paste this in the else section. Save this and we can test this over in the browser. We're currently logged in and we see the logout button and the user email. If we click logout, this is now removed and we get the text of please sign-in. We will also back-up all the security soon when we add some permissions onto the server. Next, we'll stick with the conditional rendering by only displaying the boards for the current user.
41. Rendering boards based on user: Inside of this board's view, we're currently logged in as this user, which ends in n1. Of any Firebase console, if you take a look at the boards collection, micron logged in user, which ends in n1, has created this board. If you go down to the second one, this is created by abc123 as is the third and fourth board too. Inside of our application, we only should see the board which the current logged in user has created. This of course, caused a problem because a user should only see the boards which they have created rather than other people's too. This home route already has this user ID passed in as a URL parameter. Over in the home.js components, let's open this up in the sidebar, we can pass in this parameter when we call the get board method. Inside of component did mount, we can access this dot props dot match, dot params, and then the user ID over in the app.js. If we save this file, head out to the app, this method is always inside of this components where we can receive these props as an argument. So let's take a look for the method which we call get boards, which is just here. We already have this User ID which we added in earlier, but our present, it's not been used. The first thing to do after the board's ref, is to remove the get method. Then in place of this, what I'm going to use the where method which we've looked at earlier, which will allow us to only get the boards where the board user field matches the current user ID. As the first parameter, this is the board field name which is board.User, separated by a comma. This is the comparison operator, which is equals the third one. We want to check this against the user ID, which is being passed in from the parameters. So we can add this variable inside here. Then we can also chain on the end the order by method, which is going to return the boards in order of when they were created. We can do this by accessing the board.created@field. Then finally we can call get to pull in all of our board data over to the browser and now we don't see any boards inside of here, but if we right-click and inspect and then go into the console, we now see the message of the query requires an index. Just like earlier this is because we're now using a more complex query. So we can now click on this link to create this in Firebase, and then like we did previously, we can go ahead and create our index and then it gives a few moments to create. Once this is done, we're now going to go over to the database. So click on the Data tab and then we're going to remove all of these boards. I also have a spelling mistake here where this should be created at. So it also fixes in just a moment too. Let's leave the collection, type in the name of boards, since some are easily created by a hard-coded user of abc123. Now let's go to the create board form and in the board object just here, we can now created at just here. Service files and now the new boards will now have the correct data. Inside app.js. We have everything we now need in here. So let's go over to the projects, let's create a new board. Let's call this the course ideas and it's going to be blue, create on your board and this appears good. Let's say todo for the next one. Choose a different color. So these are created for our current logged in user. Let's try logging out. We don't have any redirect or error messages setup just yet, but we will handle this in the next video. Now let's go ahead and sign in with a separate user so we can check these boards and not displaying for a different account. Add the email and password and then login. We also need to grab the ID for the second user. So from authentication, let's grab the user ID, now we can go over to our project. Forward slash paste this in and then forward slash boards and now we don't see the boards created from our previous user, since these are filtered down by our user ID. Let's try creating a new board for this one. So test in create a new board, good. Now, any new boards which we add will only show off for the user who created them. Later in this section, we will also introduce some security rules on the server, to help prevent this two. Next though, we will improve on the user's sign-up and login experience by providing redirects and error messages.
42. Redirecting and error messages: Let me log in and also log out. We know by the header up at the top, that's how a user state is changing, but we also want to be redirected to. After we log in, we should be taken to the boards page and I logout, should return us back to this login page. We also going to add some error messages too when signing in and also logging in, so let the user know if their email and password was wrong or if the user's email is currently taken when signing up. All the in the off context file, which is the off context dot js. We have all of our user related methods inside here. It's going to be in here where we ask the redirects. To use redirect, we need to access the react router. Let's scroll up to the top and we can pull this from our routes package. The package name we want to import is we've router, which we've used earlier, and we import this from the react router dom. Then as we know from early, we also need to wrap this component when exporting. Let's scroll down to the bottom. I'm going to take out our auth provider, which we export in here, leaving in the consumer. Then are they export default above. We can then wrap our components with router, person in the auth provider. Save this file and then over in the app dot js, inside of this file about the top, we also need to change the import since it's now a default export by removing needs surrounding curly braces. With this now in place, we can go back to our off context and then first we need to setup an off message into states. Let's go up to our state's objects. Then just after the user, we can add a off message. Which we're going to set initially to an empty string, go down to our sign up method. Once a user is signed in, we can then redirect to the boards URL, which is made up of the user ID. After we sign in with the email and password, we can access this, dot props, dot history, dot push to access the push dates of the router. Then inside of the back ticks, we're going to insert the URL, which is forward slash. Then as a variable, we can also insert our user ID, which is available from this, dot state, dot user, dot ID. After this, we also need to go to forward slash boards, is then going to be the cut section below which receives any error messages and we can use the message to set the state. Inside here we can remove the comments. Then we can set the states and this state is going to be equal to our error message. We can set the off message to be equal to error dot message. Below this the logging component is going to be exactly the same. The first thing we need to do is to cause a redirect to the user's boards. We can grab the line of code from the sign up section. We can then paste this in after where we sign up with our email and password. We can also catch any error messages and set this to state too. With this dot set state. We can pass in the off message, which is again going to be equal to error message. Down in the logout method, which is below this, a logout should cause the user to redirect to the home route, which displays the login components. After we sign out and set the state, we can also redirect with the push methods. All we want to do inside here is redirect to the forward slash but at least where we catch any errors. We can also set the state which is going to update our off message. In next step to add our off message from state to the provider so it can be used inside of other components. After logout, we can also add the off message, which is going to be equal to this, dot state, dot off message. Now I have all of this in place. The component we want to use is over in the user form dot js. We can find this inside the side bar, down in our off consumer. We can also pass in this off message. There is an off message pass from states. It can be displayed just above the form. Let's scroll down to our form with the class of sign-up form. We can then add a ternary operator inside of the curly braces, where we check if there is a off message, if there is, we're going to output a span elements which is going to output our off message inside of the curly braces. If off message is false, this means that no message has been set the state, so after the colon, we can simply set this to be an empty string. Now let's save this, on to the browser and integral sign of components. We can first test this with a wrong email and password to check our message is being passed to this components. Let's find error inside of the email with the correct password. I'll plot the console. Let's try to login. We get the error inside the console and also the error message on the screen. Let me use and know that no user record has been found. Let's try adding the email incorrectly or removing a digit from the password, login. We again see a error inside the console and then the updated message on the screen. Let's correct this and correctly login, which then redirects us to the board's view. Also passing in the user ID, meaning we don't need to type these in each time we login. Let's also remove this user ID from the screen since no longer need this. This was added over in the home components. We go to the home dot js. Let's take a look for the span elements, which is right at the top here. We can remove this. Another case we can handle is a logged in user returning back to the home route, is now currently who logged in and then click on the home icon, will then taken to the sign up page. If we on this page and we also logged in, we no longer need to sign in or create an account. Instead what we need to do is add a button, which is going to redirect the user back to the board's view. We can again make use of the ternary operator to only show the form if there is no user logged in. Let's do this over in Visual Studio Code. Lets go to the user form and then the div with the class of a sign-up-wrapper. Above this, we're going to again use the ternary operator to hide or sign-up form if the user is logged in. The first we're going to do is to check if the user ID is not present. We can use this with the exclamation mark, to check if the user dot ID is not currently set. After the question mark, we can then open up our brackets. We can then wrap the rest of our sign-up-wrapper by taking these two and in brackets close it out in place. Then scroll down to the closing div, right down to the very bottom. After our closing wrapper div, we can paste this in. We can then ask the second condition after the colon, open up the brackets. Then this is the case of if the user is logged in. We then going to output a button which will redirect the user back to the board's. Let's add a H more button inside here. A onclick event handler, which is going to trigger an inline function. Let's set up an error function inside here, which we're going to create in a moment called redirects. Redirecting is taking the user dot ID, and then it takes between the opening and closing elements. I've go to my boards. This ternary operator will hide the form if the User is not logged in. If the user is logged in, we're then going to render a button, which when clicked, is going to redirect the user to the board's view. To do this, we need to create this redirect method outside of our render. Let's scroll up. Create our redirects, which takes in the user ID, set up our function and the only thing is redirect method is going to do is to push to a new URL. We can access this, dot props, dot history. Access the push method. Inside the back ticks. We can redirect two forward slash, add in our variable, which is going to be user ID, and then forward slash boards. Let's save this and go over to our project in the browser. Since we're now logged in, we can now click on this button, I'll go to my boards. This will then redirect us to our user ID, followed by the boards. As a final redirect for this video, we can also work with the home emoji up in the header. This always links to the home route but when a user is logged in, it would be better to link to the user's boards. Let's go over to our header dot js. Let's scroll up to our link, which is outputs in our emoji. As I href, instead of this forward slash, I'm going to remove this, add in the curly braces. We can make this dynamic. Then inside here we can also make use of the ternary operator to check if the User dot ID is present. If is inside of the back ticks, we then want to again redirect to the boards, which is forward slash, we then pass in the user dot ID, followed by forward slash boards. Afterwards, we can also add the else condition and then redirect to the forward slash route if the user is not logged in. Let's try this out. If we now save, alter the projects, we now logged in, let's click on the emoji. We redirected to our boards. If we now log out would then take into the sign-up form. This emoji will still redirect us to this home routes. These user redirects a something which will benefit the user when navigating around our app.
43. Roles & permissions: Now it's time to add some security rules to our database. Showing and hiding things on the front end when a user is logged in, is fine for keeping the user interface looking as it should. But we also need to setup our backend security just in case somebody bypasses these by creating a fake or modified request. This means the database will only send data when the user is logged in and only show the cards, listen boards, if they match the current user. I've gone ahead and removed the lists and cards from our database to give us a clean start for this video, since we're going to be adding a new field. The new field we're going to be adding is going to be just like the boards where we added a user ID. We're going to begin over in the boards.js components, where we create a new list. Inside here when we create a new list, we can make use of this user which is passed in via the context. To do this, let's scroll down to our form and on the onSubmit method, we're currently calling the createNewList method. I'm going to cut this out and then add a inline function inside here, which is going to take in the event information. Adding this inline will allow us to pass the user ID when calling this method. We can add back in our createNewList method, passing in the event information and also the user.id. Now with this we can go up to createNewList outside of the render, which is just inside of here. We currently receiving the event information, we also need to receive the user ID as a second parameter just after our events. Then when we create a new list, we want to add the user field, which is going to be equal to this userId, and the same for adding a new card too. Let's go to the list.js components. Inside here we currently not using any context. Let's begin by importing the off consumer at the top of this file. Let's go up to the very top. We can import Authconsumer from the file path which is. /AuthContext. Scroll down and we can now make use of this AuthConsumer component to wrap our code inside of the random method. Just have to return create our AuthConsumer, which has an opening and closing tag. Then we can create our function, which is going to be the child passing in the user inside of the curly braces. Setup the rest of our function. Then we can grab the rest of our code from this div with the class of list. Let's grab all of this, all the way down to the closing div. We can cut this out. Then paste this inside of our function. Now have access to the user via our context. If we now scroll down to where we create a new card, we can do exactly what we did in the last video. We put out our current method from the onSubmit. We can then pass in an inline function take in the event information, calling createNewCard, and then passing in the event information. Then also the user.id, which was passed in from context. Helping createNewCard, this is going to now receive this userId. We can pass this in as the second argument. Then just after createdAt, we can also add our user field, which is going to be equal to the userId. It is now in place. We can give this a try over in the browser. Let's head over to our projects and we can create a new board. Let's just go for a, b, and also log out. We can now sign in with a different user. We now redirected, that's at c and also d. Now this is going to leave us with various boards for different users. We can also add some lists and cards to test this out too. In fact, we want to go to one of the boards which was created. Let's go for c, so 1, 2, and 3 and add some cards inside here all to the console. Let's now refresh and take a look at our new descent cards. Let's go through all cards to begin with and we now have the user Id linked in these. Let's just check the list are working too. These are all working fine. Now we have these user fields. We can add our permissions. Let's click on the rules tab and we can set these inside of the database. Click on this. These default rules will allow anybody to read and write to our database, regardless of if they are registered or not. My install will allow us to match documents or collections, and also setup rules for each when reading, creating, updating, or deleting data. We first have this surrounding outer match, which will point to our database documents. You can think of this as a file path to our database. These curly braces which we have inside of here, are basically variables which can change, such as the document Id. Then nested inside, we can specify certain documents or collections which you want to secure. This example is pointing to all of the documents in our database. It's a pretty general rule. Then inside here we are allowing anybody to read and write to our database and of course this is not very secure. I have provided with this course a set of rules which you can use to replace these and I have these available on my desktop. I'm going to open these up. This is a text file. If you haven't done so yet, go ahead and download these from the course, and I'm going to copy all of these. Go back over to our database and then paste these in place. We can then hit publish to apply these to our database. These rules are broken down into three sections, one for each one of our collections. We'll have the match section which is here, where we going to match all the documents inside of our boards collection. We also have the same for our lists and also our cards. Nested inside of here we have various rules for when we want to read data, create or update data, and also delete anything from our database. Two things to note here when using these Firebase rules, we have both a request, which we see here, and a resource object, which we use quite a lot inside of these rules. This resource object contains data which currently lives in our database, such as here where we're grabbing at the board and then the user field. We then have the request object, which is just here. This request object contains an off object nested inside which holds information about the current logged in user. This line of code is checking if the current logged in user matches the user Id linked with the board. If it does, it will allow the user to read from the database. If there is no match, the request will fail and the user cannot read the information which they are requesting. Next, we have some rules for creating or updating the board. They can be also kept separate, but in our case, it will contain the same set of rules. I've grouped them together. We said before that this request object contains the incoming data. Request also has a resource object too which we're use in here, and this contains the data we are sending when creating or updating our boards. Accessing these will allow us to provide some validation to check that the data is formatted correctly before saving. Here we check in if the boards title is a string, we checking if the background is a string, the created At field is a timestamp, and also checking if the user which we've added to the board object is also equal to the user which is logged in. Then we only allow users to actually delete a board if the ball was created by the current logged in user. Everything else below is pretty similar. We setup a similar set of rules for our cards and also our lists to also secure these two. Setting up our rules is not too bad. Once we understand we adjust often comparing what we have in our database using the resource object with the data which is coming in, and this is available from the request objects. Now if we publish this and go to our project, click on the home icon. I'm logged in with one user and we can still see the boards which we created. Let's open up a second browser with a different user. If we refresh, we see the Firebase still allows us to access the balls created by each user. We can also go into each one of these. Let's try checking for our list in cards. Let's try deleting information, and this is all working. We can also test that if we copy a link from one logged in user, and paste this in to a different browser that we're not allowed to view the board information. This is now added some backend security to our application, along with some front end checks to keep the user interface in line. You can of course, add more complex rules to Firebase, but these are a good starting point to only allow logged in users, and also the board creators to view their own data.
44. Building for production: Once we're happy with our application, it's time to create a build for production. Let's begin by going over to the package.json in the sidebar. Open this up. If we scroll down to the script section which we have just here. We've been so far using the startup script for development and there is also a build script which we'll have just below to build our app for production. So let's do this inside of the terminal. I'm going to open up a new tab inside the terminal. Once we are on this, we can run npm, run build, and then set this off. Give us a few moments to go ahead and build for production and I'll see you in a moment when this is all done. Once this is done, if we now open up the sidebar, you'll notice inside of our project we now have a build folder. This contains what we need to deploy our app for production. It strips away anything we don't need, such as any development, error messages and dependencies. We've built our application using lots of JavaScript files for pages and components. Inside of this Build folder it will be bundled together. So we don't have to make a separate request for each file. It will also do the same if we have multiple CSS files too. We can see this if you open up the static file inside here, we have a CSS and also a JavaScript folder, and it's inside here where our files are bundled together. Inside here for our JavaScript bond, for example, there is quite a few bundles which are split up and have numbers in the filenames for cashing purposes. The filename that we'd made inside of it, which is this one just here, is our application code which we wrote. If we open this up you may see certain parts of our application which we recognize. So for example, if we add in here set states, we have our set state call where we set the selected Labels. If we keep going through our code, we have one for opened up the modal. So we'll see references to our code, but this is compressed and formatted for production. Inside the sidebar, we also have files beginning with a number, such as these ones just here and this is often a third party vendor code, such as any node modules we've included and these are cached separately for performance. Then the runtime filenames which will have down at the bottom. These are some web pack code to load and run our application. We still have our main index.html file, which is now pointing to our main JavaScript file inside of the build. Let's go across to our scripts. This is now pointing to our JavaScript file, which is inside of our bundle and this is the main file which we looked up before. So now we have this build folder inside of our application. We are now ready to move on to the next video and deploy our app to production.
45. Deploying to Netlify: There are lots of hosting and providers out there. But a really popular and easy one to get going with is Netlify. They also have a free option to use too. We can quickly get our site online using the Netlify CLI, which will give us a set of commands to push our application to production. We can do this over in the terminal using npm. Let's head over to our terminal and unicode npm install netlify -cli, then -g to install this globally. If you see an error when doing this, you may also need to add the pseudo keyword before this to install as the administrator. Once these CLI is installed for you, we can then run one of the commands which is provided called netlify deploy. This will open up in the browser where we need to create an account if you don't already have one. Now, we have some options of what we'd like to do next. We need to create and configure a new site by using the up and down keys and then hit "Enter". I'm going to enter through this team name. This is completely fine. We can then choose a unique site name or we can leave it blank to get a randomly generated name, which I'm going to do. I've used the Netlify CLI a few times before. If you've not used it in the past, you may need to take into the browser to log in or also authorize the application. The next thing we need to do is to tell Netlify where our Build folder is located in our project. This is simply the Build folder. They're the same. Before we make this available for the world to see, Netlify will give us a draft URL, which is basically a test site for us to see if everything is working first. Let's first begin by copying this draft URL. We can copy this, all command and click to take into the browser. Here we can check if everything is working okay. Let's sign in. Give this a test. We take into our boards. Let's try some of these. We also have our list and our cards appearing. This all seems to be working fine. However, though, if we now click on this "Home" icon in the corner, we then get an error message of page not found. This is because when we click on this homepage link in the corner, we then trying to link to a URL which ends in / our user ID and then /boards. However, we don't have this route or this link setup in our app. All of this is handled on the front end using the router. The solution to this when using a single-page application is to tell the server to always only return the homepage and then we will handle any routing on the front end. Doing this is pretty simple, if we go back over to our text editor, we simply need to add a _redirect file to our build directory root. Open up the Build folder, create a new file inside here, which is going to be _redirect. All we need to add inside here is / star / index.html 200, save this file. This will tell the server to always send back the index.html page and also a status code of 200. Now with this in place, if we go down to our terminal, we can once again run netlify deploy, send this off. It will also ask us for the deploy path one more, which is just simply build. This one now builds our application giving us a live test URL. We can click on this and try logging in. This is fine. Click on the "Home" icon. Once we are happy that everything is working as expected, we can now push this to production. We can do this with one more command down in a terminal. This is netlify deploy, then -prod, which is short for production. Also, we need to pass in the Build path. This will now give us a live URL, which we can click on, open up in the browser. Now, we're left with a live link for our project on the web, which you can now share with others.
46. Thank you: Congratulations, you've reached the end of this class. Thank you for enrolling and I hope you've had fun learning all about what React is and how we can use it to build applications using JavaScript. While building our app, we have clicked quite a lot of ground, starting at the beginning, where we looked at the basics such as setting of our app, components, life cycles, methods and prompts, working with state and prompt validation. We moved on to using forms and inputs, and how React uses both controlled and uncontrolled components for different situations. Our users also need a way to navigate through our pages. We then moved on to solving this using a front-end routing. Along with other solutions the router provided, such as router prompts and state, push methods and URL parameters. React only covers the front end of our project though, so we often need a back end service, too. At least, we hooked up Firebase to give us a real-time database to start all boards, lists and cards. Along with learning all about creating, reading, updating, and deleting data, along with various Firebase methods and user authentication services. Finally, we built our app for production and deployed for the rest of the world to see. I hope you've enjoyed this course, and I look forward to seeing you again in a future class.