**Using React Effect Hooks**
We don't really want to do that we want it to render every single time the watch list gets updated so we just say we set the dependency array to be watchlist and this really is the main use case for use effect so anytime something changes in your application and you want to update something kind of outside of your application like the local storage or a session um or some other property outside of your application you use a use effect hook and this is the perfect use case.
So whenever our watch list gets updated we need to run this hook again. We don't have an effect that's dependent on the state because we want it to update every time the watch list changes. The main use case for a react effect is when something outside of your application needs to change and you want to get notified about those changes. So let's say we're working with local storage or some other property outside of our application and we need to update the component whenever that property changes.
**The Use Effect Hook**
So this is going to set it and I think i forgot a t wait item so let's test this out so i'm going to add in tesla and now if i go to my application tab and we go to local storage we can see google microsoft amazon tesla so now if i refresh it remember well it didn't actually remember it but that's because we set it in our local storage however it's not actually pulling that information from the local storage so where do we actually where and when do we pull this from the local storage. Well it's going to be in this u-state hook so when this u-state hook runs the first thing it should do is and i'm going to copy this for a second and i'm just going to paste it here make this a comment and i'm going to put this across multiple lines.
**Setting Up the Use Effect Hook**
So our use effect hook will be setting up something similar to how we're storing it in local storage. When our application first loads, we want to look into local storage and we want to call get item for watchlist so this is going to give us a string and if we actually take a look at it it just gives us this string so we have to turn it into an array. So how do we turn it into array? We call a dot split method and we want to split it every time we see a comma.
**Splitting the String**
So let's try this out now i'm going to add tesla okay tesla's in there let's refresh and it remembers tesla let's remove microsoft does it remember that it does in fact remember that. Keep in mind i have to refresh this so if i yeah we could see microsoft's not there now i'm going to show you a bug in our application if i go to my watch list and delete it and i hit refresh nothing shows up what's going on well let's see if there's something in the console and we can see the air says cannot read properties of null so what happened.
**The Error**
Well our application loads the provider loads and then it runs this uh you state hook where it sets the default value so it does so it looks into local storage it tries to get item watch list keep in mind if we go to our application in here we can see there is no watch list so this returns nothing and if you try to uh this returns undefined and if you try to perform a dot split on an undefined that's the exact error that we're getting right cannot read properties of null reading split.
**Using Null Coalescing**
So how do we get around this issue very simple you just put a question mark right here so what this question mark does is it's going to check to see if this actually exists if it doesn't it's just going to return a null and it's not going to run this code. This is called null coalescing, i can never remember the terms but yeah so all this does is check to see if it exists if it exists perfect we'll just run the next code if it doesn't exist it's going to return null and if this returns null then we just default to this.
**Testing the Code**
So let's try this again okay and look at that it defaulted to the three despite the fact that we had cleared the local storage and we can just test this out once again and that's perfect so it looks like it's working i'm going to remove this stack overview page we don't need that let's see where is that stock overview.
**Wrapping Up**
Okay guys so that's going to wrap up this project we've implemented all of the features uh that i wanted we've gotten a chance to learn a lot of different features and functionalities within the react ecosystem things like the context api react router we've gotten a chance to work with different libraries and apis like the apex charge library as well as the finhub api and hopefully you guys enjoyed this project and i will see you guys in the next one we've reached the end of the course not only have you learned how to set up an effect hook but also how to handle null values.
"WEBVTTKind: captionsLanguage: enreact is one of the most popular front-end javascript frameworks and this beginner's course is the perfect way for you to learn how to use react this course is unlike most of the other react courses out there today instead of just a single teacher we've brought together an all-star lineup of instructors to teach this course these three instructors are some of the most popular instructors on our channel and have received well over 10 million views on other tutorials learning from a variety of perspectives can help you solidify your understanding of key react concepts this is a project-based course and it focuses on teaching you everything you need to know to start creating your own react applications first gavin lawn will start from the absolute beginning and teach you the basics of react through building a simple single page application to keep track of team members gavin has been a software developer for over 20 years and he's great at passing down the wisdom he's learned over the years next you'll learn how to make a meals app from john smilga john is one of the most viewed instructors on our entire channel so you're definitely in good hands for this second project he'll teach you how to fetch data from an external api to use in this react application finally you'll learn how to create a simple stock trading app from sanjeev thiagarajan you'll use what you've learned so far and apply it to an application that gets data from an api and stores data to local storage among other things sanjeev previously created one of the most popular and comprehensive api development courses in the world so he is the perfect person to teach you more about using apis with react and to follow along with this course all you need is a web browser every project in this course is developed using the replit online ide replit provided a grant that made this course possible so we're about to get started but let us know in the comments what you think about courses with multiple instructors hi and welcome i'm gavin lon i've been developing software professionally for many years and i'm really excited to bring you this react for beginners course i hope you enjoy it and i hope you benefit from it i've developed a very basic spa application single page application using react that we'll create in this video while we create this application we'll cover basic concepts in react let's take a brief look at the react application that we are going to create so let's say that we are a developer in a software development company where a lot of contract developers are employed on a temporary basis and assigned to their relevant teams depending on the current projects being developed by our organization team members are moved between teams on a fairly regular basis depending on the current projects being developed by our organization so the team member agility as it were is great but keeping track of who belongs to what team can be difficult for our development manager at times the development manager has asked us to develop a basic spa application where he is able to use the application to allocate team members to their relevant teams and can use the application to keep track of the teams and team members on the home page you can see that at the top here we have a drop-down list that contains the names of the teams in our development department below the drop-down list we have a number of cards displayed in a tabular format each card represents an employee the cards that have a dark box shadow surrounding them are the team members that belong to the team currently selected in the drop down list you can see at the top of the page status is presented to the user displaying how many members the selected team currently contains the count of the relevance team members in the selected team changes dynamically and appropriately as the selected item in the drop-down list is changed the user is able to add a new member to the selected team by simply clicking on a card that does not have a dark box shadow surrounding it once the card is clicked a dark box shadow appears around the relevant card and this means the relevant employee represented by the card is now a member of the team selected in the drop down list as a new member is added to the team the count of team members displayed to the user and the status message at the top changes accordingly we have a navigation menu at the top of the page we are currently on the home page where we are able to add team members to teams and remove team members from teams the user is able to navigate by clicking the team's menu option in the top navigation bar to a page that displays the teams and team members in a collapsible list the user is able to click each team name represented as headings in the collapsible list to reveal the list of team members that belong to the relevant team when the user navigates back to the home page the team that was last clicked as it were in the teams page will be the selected team in the drop down list and the user can then add or remove team members from the selected team when the user clicks a card on the home page that already has a dark box shadow meaning that this card represents an employee that is part of the selected team this action will remove the employee from the selected team the result of this action is represented on the ui by removing the dark box shadow from the relevant card so the cards can be toggled whereby the employee that the card represents is added to the relevant team through a click action and is also removed from the relevant team with a click action we are going to develop our spa application using replit replics is a popular free collaborative in-browser ide where you are able to code in 50 plus languages without spending much time on setup so in order to create our react application using replit you'll need to sign up for a free account with replit it's a very simple process where you are able to use your google github or facebook account to sign up for your free replit account or you can simply provide a username email address and password to sign up for your free replit account for details on how to create your free replit account please navigate to this url so you can see here i've logged onto replit and you can see that i've created a few rebels here rebel stands for read eval print loop in a bit i'll take you through a way in which you can create a rebel through raplet but for more details on ways in which you are able to create a reply using replit please navigate to this url so before we create our repl let me open a repel that i created earlier that can be seen as the prototype for the react application that we'll create in this video the finished code for this application is available on github at this url so before we leap into writing code what is react react which is sometimes referred to as a front-end javascript framework is a javascript library created by facebook react is a tool for building ui user interface components how does react work very basically react creates a virtual dom document object model in memory react is very fast react finds what changes have been made and changes only what needs to be changed so let's create a repel for our react application to create a rebel we can click this create button here you can see in the drop down list we have a number of programming languages and developer platforms that we can choose from but we want the react js item in the title field we can name our repo whatever we choose i'm going to name my reple team member allocation then let's press the create rebel button great and our environment is set up for our ripple it's that simple we can now build our react js spa application let's quickly create the traditional hello world application and look at that when we change the output in the app.jsx file it is immediately reflected in the output of our application before we get started building our application let's remove the default css code in the app.css file this is the file where we will include all of our css code for layout and styling purposes we are also going to use bootstrap 5 for layout and styling purposes we'll look at how we are able to integrate bootstrap 5 into our application a little bit later so let's create three ui components using react these ui components are represented in jsx files i'll explain what jsx is in just a bit so let's create a jsx file named header.jsx like this let's create a jsx file named content.jsx and let's create a jsx file named footer.jsx let's create the code for our header component in this video i'm going to teach you the modern way of developing a react application which uses functional components rather than class components for more details on class components and functional components in react please navigate to this url i'll represent our functional components using javascript arrow functions so for example a javascript function can be represented using this syntax you can also represent the same function as an arrow function using this syntax if the function contains parameters the arrow function representation of this function would look like this for more details on arrow functions please navigate to this url all the references to links in this video can be found below in the description of this video so the code for the header component simply outputs this html code to the browser we are now able to reference the header component in our application declaratively by appropriately including a header element within the app.jsx file we first need to import the header component into the app.jsx component to do this we can include this line of code at the top of the app.jsx file like this and now we can include the relevant header element appropriately within our app jsx file great let's take a quick pause and look at the structure of our react application if we open the index.html file you can see that we have a div element with an id of root we also have a reference to the index.jsx file within the index.jsx file the container const is referencing the root element you can see here the render function is being called to render the app component within the root element so let's create the code for our content component to get the basic structure for a functional react component let's copy the code from the header component and paste it into the content.jsx file and appropriately change the code to suit our content component let's do the same for the footer component let's write code to import the content component and the footer component into the app component let's appropriately include the content element within our app component and let's also appropriately include the footer element within our app component so as mentioned earlier we are going to use bootstrap 5 for styling and layout purposes in our application we are easily able to install bootstrap 5. so to do this let's click the icon here representing packages let's search for bootstrap and this is the package that we want to install to install this package let's click the plus icon here great to have access to all the bootstrap 5 classes within our react application we can include this import statement within the index.jsx file like this to double check that our bootstrap package has been successfully installed we can open the package.json file great to test that bootstrap is working as expected let's include a few bootstrap classes within our h1 element in our header component great notice here that i've used the class name property within the h1 element rather than the class property in a plain html web page you would use the class property for this purpose to reference a css class or classes in a react application we must use the class name property for this purpose because the class keyword is used in javascript class is a keyword in javascript and jsx is an extension of javascript that's the principal reason why react uses class name instead of class for this purpose so what exactly is jsx jsx stands for javascript xml jsx allows us to write html in react jsx makes it easier to write and add html in react it is just an xml like extension that allows us to write javascript that looks like markup and have it return from a component so within the component we have here the return keyword the code that the component returns is jsx code that represents the markup that we are returning from the component it's important to note that jsx is not valid javascript so browsers can't read it directly so what's known as a transpiler translates it to react dot create element calls transpilers a compiler that translates one form of syntax to another like babel or typescript compiles the jsx into appropriate syntax that browsers can understand let's remove these bootstrap classes here and start to develop the functionality for our application let's create a file named employees.jsx let's copy the basic code structure for a functional component created in our header component and paste the code within the employees.jsx file so let's write code to import the use state hook into our employees component we can do this with this line of code i'll explain what a hook is in react and the functionality made available through the use of the used state hook in just a bit we are using the use state hook in this case so that react can track the state of an array of objects that contain details about our employees so we can set a default value for our use state hook by passing in an appropriate argument to the hook here so we want to pass an array of employee objects to speed things up a bit we can copy the code for the relevant employee array from this location on github and appropriately paste it into our code here like this so let's look at the code that we have just created regarding the use state hook and let's understand the purpose of the use state hook if we navigate to this url the react docs describe hooks as follows hooks are a new addition in react 16.8 they let you use state and other react features without writing a class you can see here in an example where the use state hook is used within a functional component the equivalent functionality can also be achieved using classes but of course the code is different when using class components when compared to how we write the code using functional components a hook is a special function that lets you hook into react features for example use state as a hook that lets you add react state to functional components so when would i use a hook if you write a function component and realize you need to add some state to it previously you had to convert it to a class now you can use a hook inside the existing function component what does calling use state do it declares a state variable our variable is called employees but we could call it anything this is a way to preserve some values between function calls use state as a new way to use the exact same capabilities that this dot state provides in a class this javascript syntax is called array destructuring it means that we are making two new variables employees and set employees where employees is set to the first value returned by use state and set employees is the second so basically the first item is the employee data the state of the employees data is maintained in this item the second item is a function reference and is used wherever we need to change the state of the employee's array stored in the first item here so basically the use state hook returns a pair of values the current state and a function that updates it when the state of the employees array changes through a call to the set employees method our employees component is re-rendered to the user's browser the markup jsx code that we'll write in a bit denotes the html code that is re-rendered to the browser so i'm going to quickly demonstrate writing code within the employees component to output a list of each of the employees full names to the screen you don't need to follow along with this part of the video as this is just to demonstrate outputting the relevant markup from our component to the user's browser let's write code to import the employees component within the app component let's replace the content element here with the employees element great so we of course don't just want to output a list of employee names to the screen we want to output the employee details within cards to provide a better ux user experience before we create the code for this let's upload two images that will be appropriately displayed in our employee cards let's first create a folder named images where we'll house our images that we are about to upload you are able to download the relevant images from this location in github you are then able to upload the images like this we can then drag and drop the images into our images folder like this great let's write the code to output the employee data as cards to the ui firstly let's import the image files like this into our employees component notice how when returning jsx code the markup related code must be contained within one element one element must be returned from jsx code if you wanted for example to return the p element and the image element without wrapping these elements in for example a div element react allows you to wrap the relevant elements in empty tags like this in our case we are going to return markup that is wrapped in one element let's write code to return the relevant markup from our employees component note that we are using semantic html here so instead of just using a div element here we are using a more descriptive main element here for layout purposes let's set our main element's class name property to the bootstrap container class for layout purposes let's nest a div element within the main element let's then nest another div element within the development that we have nested within the main element let's set the class name property of the first div development to a bootstrap class that denotes a new row in our pages layout let's set the class name property of the div element we have nested within the row development to a bootstrap class that denotes a new column so i'm using relevant bootstrap classes for these div elements appropriately for layout and styling purposes i won't go into details of these bootstrap classes in this video because i want to focus on react please navigate to this url for more details on the bootstrap grid system we are using javascript's map method to map the data for each item in our employees array to appropriate markup code that will render a card for each employee in the employees array great our cards are displayed as expected to the screen let's center the cards using these bootstrap classes here great i want three cards to be displayed per line so i'm going to use the css grid for this purpose so let's wrap the cards in a development let's set this development's classname property to a class that we'll write in just a bit named card dash collection let's open the app.css class and include the appropriate code for our card dash collection css class so we are setting the display property to grid here and then appropriately setting the grid dash template dash columns property so that each row of cards contains three cards on the ui excellent let's use an appropriate bootstrap class to create an appropriate amount of space around each of our cards this bootstrap class is simply appropriately adjusting the margin property of each of the cards great that looks much better we want the user's mouse pointer to turn into a pointing hand icon when the user hovers the user's mouse over a card we can ensure that the appropriate style of the user's cursor pointer is applied by including this code within the relevant div element that represents a card note that because this is jsx code and not typical html code we must set the style property within the relevant div element to an appropriate javascript object that represents the appropriate css code rather than the literal inline css code that we would apply if we were just writing html code in the case of javascript objects like this it can be confusing for react beginners because you have two curly braces one for the jsx and one for the javascript object notation one of the great things about jsx is that we are able to include javascript logic within expressions to determine what markup code we want to render for our components so we can use curly brackets to tell react as it were that the code within the curly brackets contains javascript logic within the javascript logic we can return html markup related code so let's write a javascript expression that uses a ternary operator to evaluate the gender property of each employee based on this property's value an appropriate image element is returned from our javascript logic great let's create code to output a drop down list containing our teams so for the sake of the example i'm just hard coding the teams in the real world you'd likely retrieve the data from a database through a call to for example a restful web api component great but the select list or drop-down list could look a lot better a really simple way to make our drop down list look better is to use these bootstrap classes great so whenever the user changes the currently selected item in the drop-down list we want this to change the state of our component so to do this we are going to once again use the use state hook so here the selected team variable will store whichever team is selected in the drop down list the second item set team is a function that we can use to change the state of the selected team variable when the set team function is used to change the state of the selected team variable our component will be re-rendered so when our component is first loaded our component is rendered when the user selects a new item in the drop-down list our component will be re-rendered this is because whenever a user selects a new item in the drop-down list our component state has changed and therefore a re-rendering of the employee's component is triggered we can pass in a specific team name as our default value to the use state hook let's pass in team b so when our component is first rendered team b will be the selected item in our drop down list so the next step is to set the value property of the select element to the selected team variable so you can see how react is now able to keep track of the state of our component and render the component appropriately in response to state changes we need to use the set t method to change the state of the selected team variable in order to know when to change the state of the selected team variable our component needs to know as it were when the selected item in the drop down list changes we can use the javascript on change event for this purpose so let's appropriately wire up the onchange event to a method that we'll write in just a bit named handle team selection change let's write the handle team selection change method so we can use the event argument that is passed into our handle team selection change method by default to get the value of the item selected in our drop-down list we can then use the set team method to change the state of the selected team variable this means that when the user changes the selected list item in the drop down list that this action changed the state of our component and our component is then re-rendered let's write codes to log the new selected items value to the console window in our browsers great you can see that we have a few warning messages logged to our console window we'll address these issues as we develop the application i'm in a bit of a bad habit of using class instead of class name when applying css classes to elements please note whenever i forget to use class name and use class ignore me and rather use class name to apply css classes to the elements in your jsx code so we want to add a box shadow around our cards when a user clicks a card on the ui meaning that the user is adding the card representing an employee to the selected team in our drop down list so if the relevant card does not already contain a box shadow around it a box shadow will be added to the relevant card so if the card already has a box shadow surrounding it when the user clicks this card the box shadow will be removed from the relevant card meaning that the employee has been removed from the relevant team selected in the drop down list so basically we want to write code so that whenever a user clicks a card that a box shadow effect is toggled for the relevant card so to do this let's use the on click javascript event and wire up an event handler method to this javascript event named handle employee card click we are going to call the map function on the employees array to return a transformed array where the relevant employee item which in this case is denoted by a card that has just been clicked on the ui within the array is changed in accordance with the team selected in the drop down list so for example if team a is selected in the drop down list the employee item represented by a card that has just been clicked on the ui will change whereby its team name property will be set to the team selected in the drop down list if an employee is already a member of the selected team the card representing the employee will have a box shadow around it when a card with a box shadow around it is clicked the relevant employee items team name property will be set to an empty string the box shadow will be removed from around the relevant card on the ui so the map function traverses the employee items in the employees array the ternary operator checks to see if the employee represented by a card on the ui matches the current evaluated item in the employee's array if a match is found the evaluated employee item's team name property is changed accordingly so basically when a card is clicked if the employee that the card represents is already a member of the team this functionality will cause that employee to be removed from that team if the employee however is not a member of that team that employee will be included within that team once all the employees have been traversed by the map function the newly transformed array is returned and assigned to the const named transformed employees our code is then using the set employees method to change the state of the employee's array this state change then triggers the employee's component to re-render so how do we reflect the change in the state of the employees array on the ui we can add a css class that contains an appropriate box shadow property to the clicked card element or remove the relevant css class if it already contains the relevant css class so we are essentially toggling the css class to create this effect the effect of adding and removing the box shadow from the relevant card so we can achieve this in code by including an appropriate ternary operator that returns the appropriate css code to the appropriate class name property within the relevant div element that represents a card so if the employee's team name property is equal to the team selected in the drop down list ensure that a css class named standout which we'll write in a bit is referenced in the relevant div element else ensure that the standout css class is not referenced in the relevant div element i.e the development that represents a card the card of course represents an employee so let's write the code for the standout css class let's open the app.css file let's add the standout.css class let's include the box shadow property within the standout css class and provide the appropriate box shadow settings excellent so we now want to output status information from the header component whereby when the selected item in the drop-down list changes a count of how many team members exist in the selected team is presented from within the header component to make it easy to communicate state to both the header component and the employee component we can include the state-related code that currently resides within the employees component in the app component which is the parent component of both the employees component and the header component so let's cut the state-related code from within the employee's component like this and appropriately paste this code within the app.jsx file like this let's cut the code that imports the use state hook into the employees component and appropriately paste this code into the app.jsx file now in order for the employees components to be able to effect state and respond to state change we need to pass down the state-related items to the employees component from within the app component we are able to do this in a react application by passing the relevant props to a child component like this prop drilling is an unofficial name for passing props to a child component from a parent component let's take a moment to understand the concept of props in react let's navigate to this url what are props in react we use props in react to pass data from one component to another from a parent component to a child component or components props is just a shorter way of saying properties they are useful when you want the flow of data in your app to be dynamic how to use props without destructuring we are going to use destructuring but let's first understand how to use props without destructuring to use props you have to include the props parameter within your function this is similar to passing arguments into your regular javascript functions here's an example so you can see here the values for the name prop and the tool prop are being passed down to the tool child component within the tool component these prop values can be read through the props object like this so we are passing in our props values from the app component to the employees component in a similar way but we are going to use destructuring to read the relevant props values from within the employees component the next step is to include these props within the function that denotes the employee's component so instead of the props object being passed to our employees component we are destructuring the object into its individual property values so through destructuring we don't have to reference within our employees component the relevant values with props dot preceding the relevant properties destructuring in a javascript expression makes it possible to unpack values from arrays or properties from objects into distinct variables so here we are unpacking values from properties of a javascript object into appropriate distinct variables great we can now use prop drilling to pass in the selected team and count of the number of members of the selected team to the header component we can use javascript destructuring to unpack the relevant props in the relevant object into appropriate variables let's change the header of our header component appropriately let's include code to output the count of team members within the selected team to the browser excellent let's use bootstrap to include appropriate layout code for our header component great let's write code in the app.css file so that text within h1 h2 h3 h4 h5 and p elements are horizontally aligned centrally let's include some basic code in the footer component with some appropriate layout code provided by the relevant bootstrap classes great local storage so every time the state changes for either the employees array or the selected team variable we want to save their values to local storage in react we are able to implement the use effect hook to track state changes for specific variables when a particular state change occurs code passed as a function to the use effect hook can run that appropriately saves our state to local storage so let's see how we can do this in code in the app component where we are importing the use state hook let's also provide code so that the use effect hook is also imported from react we can then pass in an arrow function as an argument to the use effect hook so the first argument denotes the code that we want executed when a certain event occurs for example the state of a variable changes the second argument denotes the event that must occur to trigger the function passed in as the first argument i.e the function that we want executed if however we passed in an empty array like this as the second argument the function passed in as the first argument would only execute when the component first loads in this case we want the function passed in as the first argument to the use effect hook to run when the state of the employees array changes so this is when a user clicks on the card and a team name for an object within the employees array changes ie when its team name property changes to the selected item in the teams drop down list so to do this we can pass in the employee's variable wrapped in square brackets as the second argument then we can appropriately call the local storage dot set item function to save the employee's array to local storage so when the stage changes we are updating the employees array in local storage we can use another use effect hook to save the state changes to the selected team variable to local storage like this great we can then use the localstorage.getitem function to get the value of the selected team saved to local storage rather than the hard-coded value we currently have here that is currently setting the state of the selected team variable by default so by default we are going to be setting the value of the selected team variable from local storage if it exists in local storage if it doesn't exist in local storage it will then be set to the hard-coded value i.e team b so if the relevant value exists in local storage the relevant value in local storage will be passed in to the use state hook and set the selected team variable by default to the appropriate value saved to local storage so we are using what's known as a short circuit evaluation for the javascript expression passed as an argument to the use state hook here what this means is that when javascript evaluates an or expression if the first operand is true javascript will short circuit and not even look at the second operand so we can apply the same logic for the employees array like this so the state of our application will now be persisted to our browser's local storage great one thing i forgot to do is to include an appropriate key attribute within the div element that represents a card that denotes an employee object within a list of employee objects the key attribute helps react identify changes within a list of elements so whenever you have code displaying a list of uniquely identifiable elements it is a good idea to include a key attribute and assign the key attribute to a unique identifier in this case the key is assigned the id of the relevant employee object just to get rid of some of the warning messages i'm getting in the browser console window i'm going to track down where i'm using class instead of class name great routing react router dom the next step is to create functionality so that we can navigate between two of the main components within our react application we have already created one of the main components which is the employees component we'll create the other main component in just a bit which will be named grouped team members so we want to create functionality so that a user through the use of a navigation bar positioned at the top of the web page can navigate between the employees component and the grouped team members component while the header and footer components remain rendered to the screen so we are going to create a nav component that will appear at the top of our page so that the user can speedily navigate between the two main components so let's start by installing the react router dom package let's click the package icon here let's type react-router-dom as search criteria here this is the package we want to install so let's click the relevant plus icon to install the package great and if we open the package.json file we can see that we have installed the appropriate react dash router dash dom package within the app.jsx file let's import the components that we need from the react router dom package let's wrap our header employees and footer component within the router element each component that we want to navigate to will have its own root element so let's create a root element for the employee's component we want only the employees component to render along with the header and footer components when the user first loads the application so the employee's component renders between the header and footer components when the url does not contain any path information then we must include an element property within the relevant root element and set this to our employees element like this then let's include a root element pertaining to the navigation to the grouped team members component let's set its path property to forward slash grouped team members this is the path to a component that we are going to create in just a bit this component can be seen as the other main component of our application the two main components are the employees component and the grouped team members component let's appropriately set the element property to the grouped team members element like this so basically if the browser contains the path to the grouped team members component then the header component the grouped team members component and the footer component will be rendered to the ui the employees component will not be rendered to the ui if no path is provided along with the url of our application i.e no particular path is provided to a specific component then the header component the employees component and the footer component will be rendered to the ui and the grouped team members component will not be rendered to the ui so let's create the grouped team members component with minimal functionality at this point we'll create the appropriate functionality for the grouped team members component once we have written the code for the navigation functionality let's import the grouped team members component into our app component if we type in the path to the grouped team members component in our browser you can see that this component is appropriately rendered to our ui along with the header and footer components great if we remove this path the header employees and footer components are rendered to the screen excellent let's create a file for our nav component named nav.jsx let's write codes to import the link component from within the react router dom package the code for the nav component will basically rely on bootstrap classes for layout and styling purposes so within the first unordered list item let's include a link element that navigates the user to the home page within the second unordered list item let's include a link element that contains the path to the grouped team members component let's import our nav component into the app component let's appropriately include the nav element within our app.jsx file we now have a navigation menu presented to us at the top of our page our navigation functionality is working as expected but we want the navigation links to be displayed next to each other rather than on top of each other like this oh and the problem is that this class should be expand rather than expanded great that looks much better so if the user types in an invalid path we can include a route to handle this to do this we can include a root element below the existing root elements here we can set its path property to a wild card character which will act as a catch all for urls that don't match the paths declared in the root elements above this root element so let's set its element property to a component that we'll create in just a bit named not found so let's create the not found component this component merely outputs a message to the screen stating that the requested page could not be found great the next step is to write the code for the grouped team members component let's open the grouped teammembers.jsx file let's import the use statehook let's include javascript destructuring code to destructure the props that we want passed into our grouped team members component into appropriate individual variables let's go to the app component and write code to pass in the relevant props to the grouped team members component let's go back to the grouped team members.jsx file as stated earlier the use state hook returns a pair of values the current state and a function that updates it the set group data function will be used for changing the state of the grouped employees array let's pass in a call to a function named group team members to the use state hook that will return the default value of the grouped employees array each object in the grouped employees array will contain one property that stores the team name a property that stores the employee data for employees that are part of the relevant team and a property named collapsed the collapsed property will store the state for a list item in the collapsible list that we are going to return from the grouped team members component when a user clicks a team in the collapsible list as it were the collapsed property for the corresponding object will be set to the opposite boolean value currently stored in the relevant collapsed property this state change will cause the component to re-render and the relevant list item will either be in a state of collapsed or expanded we'll write code in a bit to return the appropriate ui markup from this component so that this state change will be appropriately reflected on the ui so the collapsed property facilitates toggle functionality whereby a list item in a list of teams can be collapsed or expanded by clicking on the relevant list item when the list is expanded a list of the relevant teams team members are presented directly below the team list item when an expanded list item is subsequently clicked the relevant list item will be collapsed whereby the relevance team member data will be hidden we are passing a function named group team members to our use state hook here this function will return an array of objects that will be the default state stored in the grouped employees array so let's write the code for the group team members function this function simply returns an array of objects where each object stores a team name a list of team members and a boolean property named collapsed the collapsed property denotes whether a team list item displayed on the ui is in a collapsed or expanded state please note that i would not write code like a code i'm about to write for the group team members function in the real world and the relevant code is only meant to set up relevant grouped data for this example we are going to flagrantly violate the principle of dry don't repeat yourself in this code so the purpose of this function is to transform the list of employee objects stored in the employees array and group the employees into their appropriate teams based on the team name property value for each employee object so let's declare an empty array at the top of our method named teams let's use the javascript filter function to return the team members for team a using the filter function called on the employees array let's create the object that contains the team name for team a the employee objects representing the members of team a and then let's include a property named collapsed let's use a ternary operator to initialize the value of the collapsed property if the selected value in the drop down list is team a then we want this list item to be expanded and display team a's team members so in this case we set the collapsed property to false else the collapsed property is set to true meaning the list item is collapsed and the relevant team members for team a are not displayed on the ui let's write code to add the relevant object to the team's array let's repeat the same logic for the other teams let's write code to return the appropriate ui related code from our component so to do this let's map the data stored within the grouped employees array to the appropriate collapsible list of teams so to handle the event where a user clicks on a team list item let's wire up an on click event within the appropriate div element to a method that we'll create named handle team click let's write the handle team click event handler method in this code we are using the map function to traverse the items in the grouped employees array if team name matches the id of the clicked item then our code knows as it were which team list item was clicked and which items collapsed property value to appropriately change in the array so our code changes the relevant collapsed property to its opposite value of course the collapsed property is a boolean value either true or false this is to create the desired toggle effect for our team list presented on the ui the map function returns the transformed array we can then write code to change the state for the grouped employees array by appropriately calling the set grouped data function we can also call the set team function that has been passed in with the props from the app component to set the selected item in the drop-down list on the employee's component appropriately we are able to change the state for the employees component through the relevant props passed into the grouped team members component so this has facilitated dynamic communication if you like between the grouped team members component and the employees component so appropriate changes made in either of these components the employees component or the grouped team members component will appropriately be reflected in the other component so the collapse functionality is currently not working the reason for this is that i've used a class named collapsed to create the collapse effect in our list this class doesn't exist in our application a class that i meant to reference here is a bootstrap class named collapse when this class is present in the relevant div element a list of team members will not be displayed for the relevant team when the collapse class is not present within the relevant development the list of team members will be displayed directly below the relevant team item let's just quickly fix a small issue here where there is only one member in a team and we want our ui to reflect one team member rather than one team members lastly let's neaten up our code a bit by appropriately abstracting certain functionality into their own components so for example we can abstract this code within the employees component that renders the drop-down list to the ui into its own component so let's do this please feel free to reference the relevant code at this location on github if you get stuck at this point let's abstract the code that traverses the employees array into a component named team members a component named team member card is called from within the team members component we can include the code that resides within the employees component that renders the cards to the ui within the team member card component so let's create a component named team member card that renders each card appropriately to the ui the code is now much neater great let's include a media query within our app.css file so that on small screen sizes each card is presented in a new line so by doing this we are making our spa application responsive excellent note that i've created two versions of this application that can be found on github the version that we created in this video can be found at this location as an added bonus i created another version of our application on github that can be found at this location in this version of the application i have implemented code for abstracting the management for passing data between components through the use of context let's navigate to this url and read a bit about context context provides a way to pass data through the component tree without having to pass props down manually at every level so by using context we can avoid prop drilling in a typical react application data is passed top down parent to child via props but such usage can become cumbersome for certain types of props eg local preferences ui theme that are required by many components within our application context provides a way to share values like these between components without having to explicitly pass props through every level of the tree the application that we have created is small and fairly basic when an application grows it may be better to use context so that the code used to share values between components is neater and easier to maintain please check out this version of the code on github to see how i have implemented context for the purpose of sharing values between components without using prop drilling with react you can break down an interface into reusable components that allow you to build dynamic user interfaces react can be described as a mature javascript framework and it has an enormous community supporting it the performance that react provides makes it an excellent choice for the implementation of front-end user interactive functionality i highly recommend learning this technology now that you've learned the basics of react with gavin it's time for you to apply that knowledge to a more complex application john smilga is your instructor for this next section hey what's up it's john from youtube channel codingaddict and welcome to our next react project the meals application and before i showcase the app let's quickly discuss the main objectives of the project and essentially there are two of them first in this project we'll learn how to fetch data from external api and as a signal during the project we'll utilize the meal db api as our external data resource and our second objective is to get familiar with app level state and more specifically context api since it's something you simply can't avoid when building more complex applications if you want to take the project for test drive just navigate to this url mealsapplication.johnsmailga.repple.co again the url is dub dub dub meals application dot johns milga dot reply dot co and as far as the functionality using this application user can search for the recipes so when the application loads we display some default recipes and if the user is interested in the cooking instructions he or she can click on recipe and here we display the image the title cooking instructions as well as original resource effectively this is where the original recipe is coming from and also we can close the model now user also has a option to search for recipes based on a search term so for example if i go here and type a now i'm going to get all the recipes where in the title there's a letter a now also user can get some random ones if he or she clicks on the surprise me notice now we're getting the random recipes and also there's an option to add recipe to the favorites so if let's say i like this recipe i can add it to the favorite now we also have an option to remove from the favorites and we can also take a look at the favorite recipe again in the model now the favorite recipes will be persisted in the local storage and therefore even if you leave the application and come back later you'll still have the recipes that you saved in the favorites so it's not just going to be the local state but also will implement the local storage for this project i also created a readme file and in there you'll find useful external resources code snippets and all the steps we're going to take to build the application i like such approach since it saves you time on taking notes essentially all the important stuff is already documented and more importantly it allows you to work on a project independently once i'm done explaining the step if you feel like working on it independently just pause the video and try to solve the challenge on your own and resume it once you're ready to see my solution lastly i will share the url basically where you can find the source code with the readme file in the following videos just remember that you can always find both urls for the complete app which we covered in the last video and for the source code in the video description below okay and we're going to start our journey by creating a new project in the replit so assuming that you've logged in or registered go to your dashboard and look for create button in there look for react template and at least i'm gonna go with default name but of course you can come up with whatever name you want for your application and once all the dependencies have been installed just click on run so we can see our project in the browser and then at the very end of the video i'll just change the title in the index.html and basically this is what we see in the browser tab so since i have logged in let me just navigate here to a dashboard and like i said we're looking for create if you want to see all your projects they're going to be down here so let's go for create we're looking for a react template and i'm going to go with this default name that they offer and now we want to go with create repel we'll just have to wait a little bit for the dependencies to be installed and once everything is ready to go we just want to go with the run so effectively this is going to open up our application in the browser tab here on the right hand side and once i can see my application in action let me just showcase that all the way in left hand side these are going to be our files then in the middle we'll have our code and in my case i'm going to keep it between 200 zoomed in and 250. so hopefully that way you can see clearly my code and i'll also change the size from time to time of the browser tab just so i have a bit more real estate here in the middle all the way in the bottom we have the console which for the most part we're not going to use and what's really cool that for our little browser window we also have the devtools so if you click on these ones notice here we can also see all the errors warnings and of course our console log and rest of the stuff now we also have this cool option of opening this one up in the new browser tab and as a result we get a bigger canvas so from time to time yes i'll switch actually from this small one to a bigger one because it's going to be easier to showcase the devtools and all that cool stuff and at the very end of the video i just want to change here what we see in the page so let me just go here with meals and app and i'll do the same thing in the index.html so let me navigate to index.html here where we have the title we can change the name so let's go with meals app let me save it and of course we can see the result in both places in the small browser window as well as the big one okay and now let's grab some assets from the complete project so first what i want you to do is navigate to this url and again the url is following we're looking for replic.com at johnsmilga and meals application now here of course it adds that hashtag readme because that's the file where i'm at but the main url is again replic.com johnsmilga meals application i want you to navigate there and more specifically navigate to app.css and then we'll talk about what we want to get from there as well as why i suggest copying readme so first let me just showcase the url so copy and paste everything that i have right now now just remove that readme now if you have a different view of the application again it doesn't change the files that you're looking for so navigate to the source folder you're looking for app css and at this point you have two options if you don't want to type css together just take the whole thing so just copy it and set it up in your project now if you do want to type the css and i'll sign up yes i'll make the css video separate so that way if you don't want to type the css together you can just skip it or if you do want to build it together then just grab everything up to the end of global styles which is going to be my case of course since we'll type the css together again this is a somewhat of a hot button topic because some people prefer typing css some don't so in this case you have an option if you want to type out the css together then just grab everything up to the end of global styles if you don't want to type the css then just take the whole thing hopefully i made myself clear and like i said in my case i'm going to take everything up to the global style since of course i will write the css for the upcoming components now i'll cover the global styles in a little bit more detail in one of the upcoming videos for now just take the css you want to get from this file navigate back to your application look for source look for app.css remove all the code that you have right now save it and you should see different result on the screen now when it comes to readme i just think that it's better if you have those steps in your application now you don't have to copy the contents i mean you don't even have to follow along as far as these steps but i think it makes more sense if you want to work on the project independently and therefore in my case i'm just going to take all the code that again i have in the complete project readme and i'll just navigate back to the project that we just started building again i'll remove all the code that is currently there and copy and paste and successfully we have acquired all the assets that we needed from the complete application so at this point i can actually close it and from now on of course we'll be doing all of our work in the application we just created and when it comes to global styles essentially you'll just find some settings for typography a reset css variables for example for colors as well as the bore radiuses box shadows and then just some general styles including some classes that i use somewhat often for example button and as i know this is something that i use not only in react projects but pretty much in every project that i make because in the long run it saves me a bunch of time since i have some preset values and that way i don't have to reinvent the wheel each and every time awesome we're pretty much done with the general info so now let's start coding and the first thing that i want to do is to set up a structure for our project and in order to do that i want you to create a components folder in the source and there are four files effectively these are going to be our components in microsoft i'm going to go with favorites meals modal and search all of them will have that jsx extension and in there we want to create a component and in my case i'll set it up as a arrow function now i want you to set up a basic return in my case i'm going to go with component name but of course you can type whatever you want in the return as long as we can see something on the screen now my personal favorite is shake and bake but of course you can for example go with heading one and dude where is my car as long as you can see something on the screen we are good to go now we do need to remember to export this as default and then in the app js we'll import all of them and set them up one by one so effectively the component is going to look something like this for example search one again i have the function i have some kind of basic return and i'm exporting as a default then we want to import all of them in app.js and set up the following structure so notice these are all the imports for our components and then inside of the main we want to go with search favorite meals and model and if you can see all the returns on the screen you're good to go and last thing that i will do at least in my case is to comment out search favorites and model why well because we'll start working in the meals and even though i do want to see that the component has been set up correctly so essentially in the beginning i do want to see some kind of return i just think it's going to be easier at least for me as i'm developing and showcasing stuff just to have the component that we're actually working in so this is how i'm going to set up the structure for the application however i'm going to do that in the following video so if you want to work on this independently then once this video ends just try to set it up yourself and if you want to see my solution i'll cover it in next video okay so let's get cracking first we need to create a components folder so let's go with add folder in the source and i'm going to go with components now there we want to add some files yep that's correct and of course we can see the list of files we need to create so one by one let's just set them up i think i'm going to set up the files first and then i'll set up one return copy and paste and just change some values so first let me add those files we're looking for meals jsx then we also want to set up a modals jsx and then lastly we have the search one so let's go with add file and we're looking for the search jsx so let's start i guess with the favorites where we want to go with our arrow function so const and in my case i'm going to pretty much name it same as the file so favorites here it's going to be my arrow function and as far as return i'm just going to go with heading 1 and i'll write favorites and then the component component and like i said we want to export that as default so export default and i think i actually want to get it in the app just right away so before i copy and paste anything let me just go to app just and we want to import that from components so favorites from and then we want to go with components and more specifically favorites file and then where we have the main one why don't we change this around and let's just say favorites so that's our component and if everything is correct this is what we should see on the screen and since i can see that that's the case now let me just go here and i'll copy these values so i'm looking for a meals one i'll copy and paste then i'll select all the instances with the command d at least that's the shortcut on a mac and then we'll change it around two meals we want to do the same thing here in the modal and copy and paste i'll just write modal and then the last one is going to be a search one so again let's select everything all the instances are favorites and let's go with search let's save it then we want to navigate back to app we want to copy and paste and we'll just set up a few cursors here so the second one is going to be meals then we'll be looking for the model i believe so let me type here model actually messed it up here a little bit so let me go with the forward slash and then lastly we also have the search one i believe so let me remove all of them and then let's go with search now as far as the structure we'll start with search favorites meals and model so let's go here search then we'll have the meals and also have the model so model over here and if you can see four heading ones displayed on the screen we're in good shape basically we're moving in the right direction and once everything is good to go then one by one i'll just comment them out like i said it's easier a way for me to showcase which component we're actually working in otherwise you might be confused by all of the heading ones that we can see on the screen now the way we can set up a comment in the hsx is actually in a following way so let me showcase that notice so we go with curly's and then inside of the curlies we go with forward slash and then star and then star and forward slash and then whatever we place here is going to be commented out again eventually we'll use those components but for now what i'm going to do is back in the app just like i said you want to set up the curlys here then we want to go with forward slash and then star then star forward slash and i'll copy and paste right away and i'll set up one for search one for favorites and one for model because we'll start working in the meal so one by one let's place them there so you cannot see the search anymore you cannot see the favorites and also you cannot see the model and now let me move this sucker down we have meals ready to go so now we can move on to our next step okay and now let's talk about the app level state and essentially it's a decision we need to make of how we're going to handle the props in our application because one thing we need to keep in mind that in react we can only pass the props down so for example in our application we're going to have favorite meals and then once we click on a meal we actually open up a modal so there's going to be a communication between the favorites component and the modal component and as you can see it's not like we can just directly pass from one to another one effectively we can either set up all the functionality here in the app.js since that's the root component again we can only pass the props down we can go with context api something that we're actually going to do and therefore i'm not going to go into more detail since we'll cover all of that in the upcoming videos and also we can go with third-party state management library for example redux or redux toolkit and then of course there's million more now honestly in this case in this particular application we actually can go with app.js approach since there's not that many levels that we need to pass however again we need to keep in mind that all the logic is going to be here in the app.js since this is a root component and then from the app we pass to a separate component now the problem is going to start as your app grows more complex and if you have more nested structure for example you have more components inside of these components then effectively becomes a pain and it's not an official name for that but it's referenced as a prop drilling where basically you pass the props down to one component then it has some nested components so we keep passing down and down and down and one of the solutions for that is using context api now once you get to really complex apps then it makes sense to use redux redux toolkit my personal favorite at the moment and some other choices that are out there so in this application i didn't see the point of actually using redux or redux toolkit and therefore the choice was really between the app.js and context api and even though in this scenario we can set up all the logic here in app.js i decided that this is going to be an awesome introduction to the context api all right and now let's talk about the context api and before we go any further let me just mention two things first if you don't find my explanations good enough i can always suggest this article by free code camp where they cover context api in a great detail now the second thing that i want to mention even though yes context api is an awesome approach still keep in mind that it has its limitations yes it's good enough for this project and it's way better than just passing down props from one component to the next one let's say seven levels deep however once your app grows and becomes really complex essentially you'll hit two roadblocks first there's less structure than for example tools like redux and redux toolkit and that becomes especially important if there's a team working on a project and the second roadblock you'll most likely hit is the fact that it's somewhat clunky to communicate between multiple contexts so when it comes to really complex application most likely you'll not only have one context api you'll have multiple and at least in my experience it's way easier to communicate between these functionalities when using the third party state management library like i keep saying redux toolkit because that at the moment is my favorite now as far as the setup for the context api again effectively it's a way for us to have all our logic in one place and instead of prop drilling where we pass the props from one component to the next one again let's say seven levels deep we can set up all the logic in one place and then that specific component can just cherry pick what data is necessary and if at the moment you're somewhat fuzzy on that don't worry once we set up the actual example it's going to become clear so first we want to create a context jsx file somewhere in our root now technically you can create the components and all that but i always prefer setting it up in the root now when i say root of course i'm talking about the source then we want to import react and use context something we're going to use a little bit later from react and we want to come up with a variable name now i always like to go with app context or some meaningful name that references the context that i'm creating but again shaken bake is also a good choice then we want to go with react dot and create context so we have this method that creates the context and once we invoke create context effectively we get back two things we get back the provider and we get back the consumer now let's not worry about the consumer right now let's just worry about how we can pass the data down and we do that with this component of provider now notice here though how we will set up a brand new component and i'll talk about the children once we actually set this one up but in here in the return we go with that provider so this is what we're getting back from that create context and then in the value prop whatever we'll pass in at the moment is just a low we can access pretty much anywhere in our application and then the last thing that we need to do as far as the provider we need to export it and we'll also export this app context and this is going to make sense a little bit later so in here i'm talking about the main item that we're getting back from create context and then we want to wrap our entire application in the app provider so the component that we're creating over here so we want to import that since we're exporting from the context and we want to wrap our application now while we're still in the index.js i want to mention that because of react strict mode while in development you'll notice multiple logs so if you're wondering hey why while i'm developing i'm getting quite a few console logs it's because of the react strict mode that's just basically a setup in development and once i've covered the general concept now let me set up the context api in our application okay so now let's set up the context in our application like i said i prefer setting up in the source so let me create a new file i'm going to go with context js and here we want to look for react and we also want to right away get huge context now we'll set this one up later we use contextual but we might as well import it right now then we want to go with the name in my case that is going to be the app context and that one is equal to react and then the method name is create context we invoke it and again we get back those two components now since i want to return provider from the component that i'm going to be wrapping the application i need to first create that component naming is up to you in my case i'm going to go with provider again this is a separate component that will wrap our application and from this component we're going to return app context dot provider very important distinction so in here we'll access children and i'll showcase that once we actually wrap the application because it's going to be easier to understand that way so let me go with return here return and we want to go with app dot context dot and then we're looking for provider like i said we get back two things the consumer and provider but with the arrival of use context we actually don't need to export it from the context.js so that's why we just need provider and then it has the value prop whatever we'll set here in the beginning is just going to be string but eventually it's going to be more complex data structure that one will be passed down to all the components and as a result we won't need to do that prop drilling now we do want to display the children against something i'm going to cover in a sec once we can actually access everything and now let's export from this file so for now we want to export the app context as well as the app provider both of them are named exports as you can see so let's save it if nothing breaks we're in good shape now let's navigate to index jsx we want to grab the provider so import app provider now that one is coming from and then of course we're looking for the context and then we want to go where we have our application and we want to basically wrap it in the app provider like so so let's wrap it again if everything still works if there are no issues then we are in good shape and it looks like i have an error and actually it's because of the name the extension should be here js6 my bad once i fix the extension everything should work as expected let me restart and yep i can see the meals component now the reason why we want to grab the children pop and set it up here in return because this is our application so essentially in react children is a special prop and that represents pretty much whatever we have inside of the component so in our case what we have inside of the component is the app one so in the app provider we have app and in our function that is represented with this children again this is a special prop that's why you go here with curly braces we structure it we grab the children and we pass it here if you won't do that basically you won't see your application notice how nothing is displayed so that's why it's important for us to grab the special children prop and then pass it down because this is our entire application and once we have set up the provider now let's see how we can access the data in any of our components beautiful we were able to set up the provider so now let's see how we can consume the data now before we proceed i actually want to make some changes in the workspace so first i noticed since i used that default name i actually don't see the working application in the dashboard essentially it's under unnamed and i've said that i'll actually change that so let me navigate here and in order to do that i just need to click on this icon and then let me go with meals meals app and then let me add temp or you know what i'll start with temp i'll go temp meals app so that way i know that this is just temporary while i'm recording okay so that's done and then the second thing that i want to change essentially is the workspace where it's nice to have that browser window but the more code we're going to write it's actually more important for me that you can see clearly all the code and readme that i'm providing and that's why i'll actually open a new one the browser one and that's the one that i'm going to use to display the results so in here we can simply close the webview then we'll have the console not technically you don't even have to close i believe the webview you can just simply push it to the side and finally i'll zoom in and hopefully it's going to be easier to see the actual code now as far as the consuming data what do we need to do well once we have set up the provider we can go to any of our components and again the magic here is following that it's not just these components in the components folder it can be any components that are sitting inside of these components and that's truly powerful because again we don't have to pass those props seven levels down and in order to consume that data we need to go with used context so we need to go to any of the components where we want to consume the data in our case it's going to be meals since that's the only one that's rendered because i don't want to get use context hook from react we want to get the app context from the context so remember when we're setting up the context this is what we're exporting correct we're exporting the app provider so the component of that wraps and from there we return the app context provider and we also exported the entire context so now in the meals we want to access that entire context so let me go back to readme and not only that but we want to invoke the used context and pass in the app context so import both things passing app context into use context and then we'll get back what will get back that value so whatever we place in the value prop in the provider and then for time being i'll just cancel log it and we should see the hello in the browser devtools so let's navigate to the meals here then we want to go on the top and import both things so import then use context that is coming from the react and then we also want to get the app context so import app context and we want to go with from and of course we're looking for the context so this is going to be right outside of the directory the components one and then let's grab the used context invoke it and pass in the app context so const this is going to be the result we're getting back so that is equal to use context and we pass in the app context and now let's simply log and i know it's probably not a big deal to see the hello but once i show you something you'll see why this is so powerful so let me navigate to the browser i'm going to open up the devtools and that is also something why i want to use the big browser window because it's going to be easier to see actually our console so let me refresh and yep now we have the hello and now you're probably wondering okay what's the big deal well the big deal is that we can turn hello into something more meaningful so if i navigate back to the context it's a prop the value one and at the moment i'm just passing the string however we can change this around and we can say that it's going to be an object so first we need to set up the curly braces effectively that means okay we're going back to the javascript line so either we can set up some kind of expression here for example variable or i can just simply pass in the object and i can go with name and then john and also let's add a roll and we'll set it equal to a student let's say that and now in the meals this is what we should see so let me again refresh and we have name john and then a role student and now we can put two and two together if we can pass in the object that means that instead of the app provider we can set a bunch of functionality which effectively is something we're going to do so we'll set up some functions then we'll pass down we'll set up some state variables that will pass down and effectively any of the components in our application will be able to access it just by grabbing use context as well as the app context and again i know i've said this 10 million times already but this is extremely extremely powerful concept because it saves us a lot of mental energy because we can set up the code in one place and then import it in any of our components all right and before we start talking about the data fetching and react now let me also show you how we can save on one import in the components that are going to consume our data so if you remember the previous video we needed to import two things the use context and app context in the component and then passing the app context in the use context what also we can do is set up a custom hook now let me just make it very clear the previous example is not incorrect there's just a better way where we can have one line of code and in order to set up we need to create a custom hook which is also something that we can do we just need to make sure that the name of the hook starts with use now the name is really up to you in my case i'm going to go with use global context and as you can see we're setting that up in the context.js and we're exporting this right away so we go to export const then whatever is the name of the hook and now notice the functionality we return from this hook from this function what we return use context we invoke it and we pass it in the app context now where did we see that one before over here so we grab both of those things in the context.jsx and remember that both of them are already present we imported the use context and we set up the app context in the context.js and then we just go with use context app context and we're returning from that hook now as a result we can import the custom hook instead in any of our components and then invoke it again the setup is almost the same we're just saving one line of code which in the long run if you have let's say 100 components makes a lot of sense so let's try this one out i'm gonna navigate back to the context one let's scroll up and it doesn't really matter where you set it up but i always prefer doing that right before the export here and now let's go with that custom hook again remember we already imported the used context from react so that is not a custom hook that's the one that comes with react which allows us to access the context and let's go with export const and then use global context and say not of course you can pass it here as well it's just i prefer this way and then it's going to be a function and then from this function what we simply want to do is go with return use context and then pass in the app context now let's try it out in the meals so let me navigate back and then instead of these two suckers we'll remove the first one and we'll change what we're getting from the context we'll simply go use global online context and now let's invoke so use global context context let's invoke that and again the result in the devtools should be exactly the same so i'm going to navigate back again i do need to refresh and check it out we still have the object with the properties of name and raw and with this in place we have successfully set up the structure to consume our data from the context.js and what that means is that we'll just have to set up the entire logic in the context.js and then each and every time we want to get the data again we're talking about the state variables or functions that we want to invoke we'll just use use global context and we'll cherry pick which info we want to get from the context jsx which again is extremely extremely powerful concept because it saves us time and mental energy in the long run and now let's talk about another extremely important topic and that is data fetching in react and let's start with the most pressing questions first where and how so essentially we can fetch data in any of our components however in our case since we'll pass this down we want to do that in the context but yes if you want to set up some data fetching in search component you can do it the same way as i'm about to show you in the context.js and the same goes for any component you create so hopefully that is clear now how we fetch data in react well we want to use use effect hook because it allows us to control when we're actually going to fetch data so if you remember from the previous videos use effect is a hook that runs after every render by default so by default it runs after every render however it also has this cool feature called the pen and zero which we pass right after the callback function so when it comes to use effect effectively we invoke the hook we pass in the callback function and then this callback function whatever code is in there is going to be invoked after every render again that is by default if we pass this dependency array and if we leave it empty then it's just going to run that callback function when the component mounts or in the other words when the component loads now we do need to understand that when it comes to context essentially it's only going to load once because it's in the root of our application take a look at the index one notice so we have this app provider that's the one that we're exporting from the context and therefore this is going to load once we open up the application again i'm not talking about the re-renders that possibly might happen after that i'm just talking about that initial load and that's the one that we actually get from this empty dependency array so when we set up the empty dependency array in the use effect essentially that means it's only going to run when that component in our case app provider loads or mounts now we can also pass here some values and then it's going to run every time the value changes but let's not worry about it i just want to make it very clear that when it comes to data fetching we for sure need to pass in that dependency array and i'll show you in a few videos what essentially is going to be result if we don't do that let's not worry about it right now and you can start simply by setting up some kind of console log in there so go to context.jsx import use effect then invoke it pass in the callback function set up the empty dependency all right and then in my case i'm just going to say aph data here now once that is done then i'll cover one more gotcha that we need to remember about this callback function and then i'll lay out the steps that i'm about to take in next video so first let me navigate to context.jsx i want to get the use effect and i want to actually invoke it as well so in here we want to go with use effect so that's the hook that's coming from react then we want to invoke it right away so let's say use effect let's set up the callback function like i said empty dependency array and then in here let's just say console log and fetch data here let's save that and now let me navigate to the browser and check it out now of course i have the console log here now what is the gotcha that i was referencing before well it's following when it comes to this callback function it cannot return a promise so you cannot turn this into a sync function because if you remember by default the moment you set up a function to be async it returns a promise and react is not okay with that so we cannot turn this into a sync function now why am i saying that well because when it comes to fetching data effectively we have two approaches we can use dot then or we can use async await so when it comes to that then if that's the approach that you prefer you can easily set up the code right here instead of the callback function you can for example go with fetch api so you go to fetch let me write here fetch then the url then we go here with that then and then you know the rest so you can definitely do it here now if you want to go with async await essentially you have two options you can set up the function here inside of this callback function and then invoke it or you can set up the function outside and then invoke it again the reason why we need to do that is because we cannot turn this one into a sync function and then call await so we need to set up a separate function so hopefully we are clear on this and now let me show you the challenge that i have for you so now that we know that we'll use used effect to fetch our data i want you to try fetch data now you can use fetch api or axios that is really up to you that is irrelevant first i'll show you the fetch api approach since that is built in and then i'll switch to axios and this is another hot button issue because every time in tutorial i use fetch api i get comments why i'm not using axios and then once i switch the axios i get people asking why we're not using fetch api look just pick the one that you use and you'll be good to go there are not going to be that many differences so pick either fetch api or axios just remember that with axios we do need to install it and this is something that of course i'm going to do in a few videos and you can use any url that's why i have here from any url in the use effect callback function so again you just need to remember that if you're using that then it's one approach if you're using async await then it's going to be another approach and for time being just log the result just log it you don't have to do anything complex just log the result try to set it up and in the following video i'll show you my solution and before we continue let me just mention that in this video i'll use fetch api and if you're not familiar with fetch api or you just need to jog your memory in the readme i shared a awesome article by free code camp and basically i'm going to use the random user api and the way it works this is the url and then essentially just returns a random user again the structure here is not particularly important since that's not what we're going to use in project i just ended up using this url because it's pretty short and straightforward and then the way i set up the logic like i said in the use effect i set up the fetch data function because again i know i've said this before already but we cannot turn the callback function into h sync since i want to use a weight that's why i created a sync function so fetch data a sync function and then since we're working with asynchronous requests i just set up the try catch as well just keep in mind that when it comes to fetch api this doesn't really worry about the errors unless they're network errors and that's one of the differences between the fetch api and axios which effectively we're going to use in the following videos so in here i went with response await fetch then passing the url and then we need to turn this into a json so i waited for response.json got back to data and then logged in and also just in case logged the error and right below where i set up the function i invoked it as well and once i set up the function in the app provider also showcase how we can move it outside of the callback function because essentially that is going to be our approach in the upcoming videos so now let me navigate to the context and then for now i just have this console log here let me remove it let's go with const fetch data is equal to async that's our function now fetch api is built into the browser so we don't need to import anything we want to go with try and catch let's come up with const response is equal to a weight fetch now let me grab the url and then let me set it up as a string of course now we have a weight okay that's beautiful then const data is equal to await and then response json let's invoke it again and now let's just log it so console console and then log and then let's pass in the data now let's do the same thing in the error we just want to change what we're logging over here and we have the function that's awesome but of course for anything to work we also need to invoke it so we go with fetch data here now again let me navigate to the browser and check it out and here i have this giant object again we're not really concerned what we're getting back the idea is just to showcase how we fetch data so that's the first step after that we'll set up the state variables and all that and now let me also showcase how we can move the functionality outside of the callback function so this is definitely one approach that you can use but in our case we're actually going to set it up outside and then we'll invoke it inside of the use effect effectively i just prefer this approach better now there are times when you want to do that and use effect but again in this case it doesn't really matter so let me take this outside so again i'm talking about the function the fetch data function um now let's see whether everything still works yep i still get back the results so we are in good shape okay and once we're familiar how we can fetch data react now let's take a look at the api we're going to use for this project and before i show you the documentation as well as the urls i actually have a challenge for you so either you can follow this link or just go to your search engine and type mealsdb regardless you will hit this link and then get familiar with docs so try to understand on your own what the api offers and more importantly get two urls get the one that allows us to search meal by name as well as the random one now here's the hint in the docs this part is missing so either you'll have to add it manually and you'll see why in a second or just take the url place it in the browser and then copy it so again you have two approaches i usually prefer the second one i just find it faster than typing and then in the context jsx set up two variables now in my case i'm going to call them all meals url and random meal url and assign the corresponding values so as you can see in here we're searching meals by name and this is going to be our all meals url at least in my case and then the random meal url is going to have this value again this is the challenge go to docs get the urls get familiar with documentation and in next video we'll do it together okay and as far as the api we'll use this one so i believe the official name is the meal db and effectively we just want to navigate to the documentation and as you can see they just provide a bunch of urls so some of them you need to be a patron and some of them are for free so these are the two that we're going to use we're going to go with search meal by name and we also use this one look up full meal or no sorry look up a single random meal got carried away over here and just to showcase what we're getting back let me just copy this one let me go to the browser and check it out so effectively we'll get back the object in there there's going to be an array by the name of meals and then each meal is essentially a object itself with bunch of properties now of course this is already a full name if let's say we change this around and just go with a we'll get more items so now as you can see we have more meals that are again objects in that array and then we've got an id we've got a image and as you can see a bunch of other stuff as well so that is as far as the search meals by the name now another option that we have is look up a single random meal and what's really cool that actually they send back that one random meal but it's still structured as an array and for somebody who built the application that is actually very nifty because you don't have to change anything as far as the logic on the front end so if i copy and paste notice i still get back that one meal correct but the structure is still the same and if you have been setting up applications with api and front end you know that it makes things easier if you don't have to restructure your application based on the urls coming from the same api now again there's multiple variations of course there's cases where it's not possible to always have pretty much the same structure but in this case this is super nifty so now we just want to take those two urls and set it up in the context so now let me navigate back to our project and then i'm gonna go to context.js i'll take a look um most likely i'll just do it above here where we have the context and then let's come up with those two variables so my case is going to be all meals url and then the value will be this one over here so that's the one where we'll pass in the search value and for now i'll just leave it as a of course eventually it's going to be dynamic and the second one will be that random one so let me navigate here and then again let's come up with that variable name in my case it's going to be random meal and then url and then let's pass in the value all right add up next we want to refactor our fetch data function where first we want to switch to the axios library and as i know if you're not familiar with the library or you just need to jog your memory here's an awesome article by free code camp and also we want to switch the url to the get meals by name one remember it was stored in the url variable and the steps are following we want to install axios so we can do it over here where we have the packages then we want to import it in the context.jsx and as far as refactoring i'm going to change the name of the function i will switch from fetch api to axios then i'll add the url parameter because we will invoke the same function multiple times with a different url eventually so we might as well do that right now and i'll pass in the all meals url so we'll switch to all meals url and lastly just log the response if you get stuck feel free to take a peek at my solution below so let's refactor our fetch data so the first step is going to be installing axios i'm going to navigate to this tab and then let's type the name of the library of course it is axios we want to install and as far as the brief intro axios effectively is a http library that makes our life easier especially as your project grows and you have more complex requests and we want to import that in the context.jsx and then i'll show you how basically our factor the application so let's start here by navigating to the context jsx and then we want to import the axios import axios from and then we're looking for the axios library and then as far as refactor let's take a look at the readme essentially we want to switch from the fetch api to the axios and i also want to change right away the name so instead of fetch data i'm going to go with fetch meals i'll pass in the url so instead of hard coding the url i'll pass it as a parameter and again the reason for that is because we'll invoke the fetch meals multiple times and based on the conditional pass in the url and in here we just go with a weight and axios so we don't need to turn this into a json and we just log the response now axios does have a kind of more complex response so we'll actually have to pull out the data but let's not worry about it right now we want to invoke fetch meals and then we want to actually pass in the all meals url now of course in your readme it's going to be already there and once we do that we should be in good shape so let's try this out in the context i already have the axios okay so that is done now let me find my fetch data i'm going to call this fetch meals then i'll pass in the url that's going to be name of my parameter and instead of console logging the data we'll take a look at the response and then instead of fetch we're going to go with axios and here we'll pass in the url so instead of hard coding this like we did previously we'll pass in the url then let's keep on moving and now we want to pass in the all meals url let's save it and let's take a look at the browser so in here there's a complaint that import from axios blah blah let's see whether refresh is going to help and nope that's weird maybe i was just too busy talking and i actually didn't install the library so let me double check i have dev dependencies okay and then yeah i have nothing here so let me go back to the installer and let me look for axios one more time that's what happens when you talk too much so let me install the package and now everything should work as expected so now let's take a look at the browser let me refresh and then if everything is correct and of course fetch data is not defined because i forgot to change the name my bad so let me navigate back to my context and then here of course i change the name so it should be fetch meals instead of fetch data let me save for the third time yep and now everything works now when it comes to actuators like i said the response is more complex so in here we actually get the config we've got data as you can see it's a giant object now what we're interested is this data property so if we are successful then data that we're getting back from the api from the server is going to be located in the data property now like we covered already before the way the api sends back the data there's a meals array so that doesn't change it's just going to be located in the data property and at this point we have multiple options either we can just destructure it or we can go with response and then data now keep in mind though the value is in the meals so still have to access that property but i'm just showing multiple ways how we can access it now i always actually prefer the the structure route where i just type data and now i directly access the data again let me say one more time and now we should see again that meals array which is an array off object and lastly let me just showcase how we can access error in the axiorys so i'm going to go back to my fetch meals we're looking for error object and more specifically we're looking for error dot response so that's where we can access the error and in order to showcase that i'm just going to go to the all meals one i'm just gonna type some gibberish here and then if you take a look at the console notice you'll have the error and in this case you can take a look at the error response as well so that should do it for the axios and now we can proceed to the next step okay and up next let's set up the meals state variable and just render something in the meals component now before i continue let me just mention that if you did also change the value in the url in the previous video just to see the error please make sure that it's back to the original url otherwise the functionality is not going to work as far as the setup we want to go with import use statehook in the context then we want to set up the state variable at least in my case i'm going to go with meals and remember that it returns an array with two values the meals value and the function that controls that and then we wanna set the state variable from our fetch meals function remember we're getting the meals from the api and remember the structure of the response and we want to use set meals to set our state variable equal to that data then we want to pass the meals down to our entire application and remember we do that in the value prop and we want to structure the meals in the meals component lastly we want to iterate over the meals log each meal and then render something on screen again it doesn't really matter what you render as long as we can see that we're getting the data we are correctly iterating over and we have something on screen we're in good shape as always if you get stuck feel free to peek at my solution below all right and as far as my solution i'll start by importing use state in my context jsx so let me add this over here then i'll set up that state variable by the name of meals and remember we get back the array we write away the structure this is going to be the value and this is the function that controls that value initially the value will be empty array and then in the fetch meals remember the array is actually in the meals property so there's a data object in there we have the meals property and in there we have the array so we run set meals this is going to set our meals state variable and we want to pass it down to the entire application that's why in the value instead of the name and whatever it was the role i believe we'll pass down the meals and then in the meals component we'll destructure it remember the setup is already in place we just need to change what we're looking for since we're passing down the meals instead of the name and the roll now of course we're looking for that property in the emails component and then lastly let's set up the return where i'm going to go with section now technically you don't have to add section we'll worry about the css in the following videos but i'll write away gold section since that's what i'm going to use but you can also use div of course then we'll iterate over the array and then for every item in my case i'm going to call it single meal that's going to be that object i want to log it i want to see the proper issue that we get back since we'll have to destructure them and at least in my case i'm going to return a heading 4. so if everything is correct i should get i believe 25 heading 4s on the screen so let's try this out first i want to go to context jsx i will look for use state then i'll set up that state variable so meals and then set meals so that's the function of course that controls it use state and i'll start with empty array because remember we'll be iterating over and initially if you'll set it equal to null then the functionality is not going to work because it takes time to fetch those meals and i'll talk about the loading and also if we get back nothing from the api what to do then so we'll cover those conditions but just remember that yes we do need to start with empty array then let's use the set meals and then pass in data and then meals that's where the emails are located and now i believe we can just remove the console log then instead of these two suckers we want to pass down the state variable let's save it and then lastly in the meals component first i want to grab it so instead of this context i'm going to destructure meals and now let's iterate over where first we want to go with section then inside of the section we'll iterate over the list so let's go with meals dot map and we pass in the callback function and i'll reference each and every item there the object as a single meal and what i'm returning from this map function well for now i'm just going to go with heading 4 and single meal and then let's also log it since we'll use those values in the following lecture so let's go with single meal let's save it and like i said if everything is correct i should see a bunch of single meals on the screen and we do and also notice over here yes there are some warnings about the key prop and all that we'll worry about it in a second for now i just want to showcase that these are the values that we get back for every object and they should match what they should match this correct so this is also what we can see in the browser and if you have the same result now we can move on to the next step okay up next let's display a nice card for every meal that we have in the array and the way it's going to look like so i'll add right away classes for css but like i said i'll do the styling in a separate video so if you already copied these styles you're good to go if you didn't then don't worry if it looks somewhat ugly in the beginning we'll worry about the css in the following videos so first i want to grab the properties from the single meal now how do i know that those properties are there well because we logged them in the last video correct and we can also of course see them in the browser if we just provide the url and the properties that i'm interested are id meal which is going to be the meal id then i also want to get the title and notice how i'll pull out the property but i'll right away give it an alias just so it's easier for me to work with the value now do you have to know of course you can still use the property name that comes from the api and also i want to get the image the property for the image is this one and yes i'll give it an alias of image so i'll set up the section center for the entire section but like i said you can also set up a div if you want and as far as the return i'm going to return a article and then when it comes to react since it wants to keep the track of all the changes that are taking place we do need to provide a key prop which needs to be a unique value now technically you can get away by grabbing the index over here if you're familiar with map you know that the second parameter we get by default is the index so you can also pass it here but it's not suggested if the data is going to be changing so if you're going to be making some kind of manipulations with the data so therefore it's always suggested to have something unique and in our case that something unique is the id then we want to add a class name of a single meal and i'm not going to repeat the whole deal about the css and we want to display the image now with the image for now i'll just go with this style and width 200 so effectively we're setting up the inline styles here simply because otherwise those images are going to be massive so yes the css is coming up so for now this is just temporary now again if you have the entire css you don't need to worry about it just add the class name of img and then right after the image we have the footer where it will display the title and also the like button now the icon for the like button will set up in the following videos for now let's just right click me and then if everything is correct we should see some images some titles and all that cool stuff so let's start working on that where first navigate back to the meals here and i'm not going to switch back to the browser and showcase where i'm getting the properties again i believe i showcased that quite a few times so first i want to pull them out out of the single meal and yes each object has them then we want to go with string meal and yes the names are a little bit funky but we'll just live with that we'll just give it an alias and we'll move on and then the last one is the string meal and then i believe it's thumbnail and that is equal to a image at least that's my alias so i'm going to set it equal to single meal now we nicely destructured it and now let's worry about the return and i'll say not i forgot to add here the class name not class i'm going to go with class name that is equal to section center and then in here it's not going to be a heading 4 will actually go with a article and then another thing that's not giving me auto complete so let me type it here article as well we do want to add a class i believe here and the class will be single meal so class name is equal to single and then meal and let's also add that key prop that basically is looking for the unique value in our case that is going to be id meal and then once we have this one in place inside of the article we want to go with img so let's set up the image let's set up the source and insert it equal to the image to the alias that we gave to the string meal and then the thumbnail and then let's also add the class name right away as well and we're gonna go with img let's close it and then right below image we're gonna go with footer and then inside of the footer let's set up a heading five setting five and then in here we wanna display the title and right next to it we'll have a button and in here let's set up again a class name it's going to be a like btn and then for now it's going to be clicking but eventually we'll set up a nice icon as well and now let's see what we have as far as the result in the browser and of course as i was setting up i forgot that i need to add essentially inline style so let me go with style and in here i want to go with with and we need to remember that since it's javascript this needs to basically be a string and now let me go back and yep now it's more manageable again it's not pretty but at least we can see some images titles as well as the like button and with this in place now we can move on to the next step okay and now let's worry about the styles now like i already said i believe ten thousand times if you have the styles you can just skip this video if you don't then we'll type these styles together and first let's just start by navigating to app.css and i want to set up the comments so usually what i do is i set up the css in the order that i have my components so eventually we'll have the search web favorites will have the meals and we'll also have the model and therefore i'll do the same thing in the app css where essentially i want to start with search then it's going to be favorites and then we want to go with meals and lastly there's going to be a model so the search and favorites are coming up for now we'll just worry about the emails and we'll start by setting up that section center and you know what also i think it's going to be easier if i just place the tab over here so that way we can right away see what we are doing so start with that section center class and you know what i'll just make it here for now of course eventually i'll set it back to what it was start with section center we do want to add some padding here and i'm going to go with three rem stop bottom and zero left and right then we want to go with with and this is the case where i'm going to use my css variable which is i believe set to 90 view widths so essentially the percent of the screen and again the reason why i prefer this is variables because that way effectively i can just set up the value in one place reuse it in multiple places and if i ever want to change something well then i need to change it in one place then i'll also set up the max width so this is for the big screen essentially i don't want any of these components spanning the entire screen i want to set up some kind of max width which i believe again if you want to double check that just navigate up to the css variables i just don't want to do that since i know that some people find it annoying but i believe it was like 11 20 pixels or something along those lines again we're looking for the variable max with and now we just want to place it in the center so we're going to go here with margin 0 and then although you know what these warnings are a little annoying so check it out now of course our container is always going to have the width of 90 of the screen but it's never going to be bigger than the 1120 so it's always going to stay like this and then we'll write from the get go set it to display grid and i'll add some kind of gap and it's actually going to be the same for the rows and columns and i'm going to go with two rems i just always prefer pretty much that type of setup and since we're on a roll when we also right away set up the column layout for the bigger screens and we'll do that with the media query and we'll go with media screen and let's go with min width and i'm going to choose the value 776 pixels and then in order to speed this up a little bit i'll copy and paste that's going to be my section center and then we're looking for the property grid template and then columns we'll set it equal to one fraction and one fraction so once we get to 776 we should have a two column layout and as you can see that is clearly the result and then we also want to add one for the bigger screen which most likely i'll showcase right away as well so in this case it's going to be 992 and now we're looking for a three column layout now as i know i'm fully aware that we can change the syntax here to let's say repeat but i just think that for this project it's good enough if we just repeat those fraction values so now let me make it bigger and notice we have a three column layout and now let's worry about that single meal we are pretty much done with the container now we want to go with single meal and of course we're talking about that card we'll start with the background property and we'll use again the css variable with the value of white and yes pretty much the actual value is also the white color then we want to add the text color and this is going to be for the button so heading already should have the text color set in css but since i want to have the same color for the button i'm going to go here with color then var and then we're looking for text color so that's the easiest variable then let's add some border radius or radius and this one will set it equal to again css variable so far and then we're looking for border and then radius like so and then we'll add a little box shadow a transition both of them see if there's variables and then once we have already single meal we'll just change that box shadow so let's start here the box shadow and let me scroll up just so it's easier for you to see so we're looking for a box shadow property that one will be equal to a shadow to css variable and then we also want to add a transition simply because we want that change to happen over time and therefore we'll go with var and then transition like so and then let's select again that single meal and let's set up that hover effect so single meal and then as we're hovering we want to change that box shadow over here and once we save it we should notice that as we're hovering effectively we're getting that darker box shadow now one thing that i want to mention remember in the previous video we added that class of image now notice that this is a global class which adds a width of hundred percent a this block block as well as object fit so now once we have the structure in place as far as the columns and everything we can actually remove that inline style so now let me navigate back to the meals and you know what let me just minimize this for now and then remember we added this style and i said that it's going to be temporary so now once we have the columns of course we can set it back and you'll notice that of course the image is spanning all across and this is exactly what we wanted so now let me navigate back to app css make this one smaller and maybe this one also a little bit smaller just so we have a little bit more real estate and then we actually want to style the image right away so we have that global class yes that's awesome but we also want to add some additional styles and therefore i'm just going to go with img so effectively i'm targeting that element first i'm going to set up some kind of height which in my case is going to be 15 rem and now let's talk about the border radius notice here how we set the border radius for the entire card but we also need to set it for the image now i don't want the border radius for every corner i actually only want for the top left and top right in order to do that we just need to go with border radius and we need to add top and then left and yes you guessed it in order to set up the right one we just need to change this value around and now we should notice that the top left and top right corners are actually around it and then lastly as far as the image we just want to add cursor pointer because in the final application we'll be able to click on image and then we will actually display it in the model then let's style a heading 5 here so single hyphen meal and we're looking for the heading 5 and in here let's add a padding 0 margin zero because there is some default uh margin padding as far as the typography let's save and then let's worry about the footer so single meal and we're looking for the footer in here let's add a padding right away so padding is going to be one rem's 1.5 rms then we'll display it as flex so display equals flex we want to align the items in the center so say align items center we want to go with justify content and space between so this effectively is just going to push them as far as possible from each other so let's say here's space between and then lastly we also want to go with flex wrap and wrap so if there's not enough space we just want to wrap it to the next line so flex wrap and equals to wrap and even though we don't have the icon we might as well style the button since we're working with the css so let's say here like button that was the class name and then we're looking for the background we want to go with transparent and we want to add the border also transparent so take this value here copy and paste and then after that let's increase the font size again for text it probably won't look that good but once we set up the icon it's going to be good enough we're going to go with 1.5 rems so increase that then cursor pointer and again the transition so cursor pointer and for transition just so i can save a little bit on typing i'll just grab the value from the single meal and set it here and as we're hovering what do we want to do well let's add some transition so like button hover and then as we're hovering essentially we wanna change the color to red so color is going to be equal to a css variable and the value is red dark and also we want to transform so let's go transform and let's translate in the y direction and since i want to lift it up like two pixels i'll say negative two pixels so now check it out as we hover over the like button we actually lift the text up a little bit and essentially that is the css for our meals component and while we're still on a topic let's also knock out the icon and effectively for my project i prefer react icons library for a variety of reasons first of all it offers tons of options and second it's very easy to work with library because you get back the component the react component and as a result you can add the class you can style it directly and all kinds of cool things so if you want to utilize the search engine just look for react icons or you can just follow the link that i provided in the readme and once you get there you'll see this documentations page like i said uh you have tons of options so these are all the libraries that you can work with and if you want to search for specific icons so let's say in our case if we're looking for thumbs up icon just type here in the search box and i believe i used this one over here now don't quote me on that essentially i will showcase that in a second but i believe that's the one that i used and just keep in mind that once you choose the icon you also need to remember which library is it from because when you import the icon and as i say not the syntax is following where you go with the name you also need to provide the library otherwise essentially you'll get the error so now let me try it out in our application where first i want to go and install the package i believe the package name was a react icons and i should get the suggestion hopefully yep there is that's the package we want to install then we want to navigate of course to the meals that's where we are setting up that icon so meals over here and now let me grab right away the value so again let me search for it and that's the one that i want to use notice the name was copied to our clipboard and then we want to go with import get the icon from and then we're looking for react icons but very important you need to add the library in my case that is bootstrap and then where we have the like button instead of just click me i'm just going to go with this component and since i want to save a little bit of time on typing i'll just copy and paste the component now let's save it and take a look at the result in the browser and now check it out instead of the text we have a nice icon from the bootstrap library beautiful and once we're done with our meals component well almost done there is a little bit of functionality coming up but the main setup is done before we continue i also want to showcase why we want to use a user effect and feel free to just watch the video i mean you don't have to follow along because i will purposely set up the infinite loop just to kind of underscore the point that i was making previously so if i navigate to context js and if i decide to be a rebel and then instead of using the dependency array and for now leaving it empty basically invoking this callback function only when the initial load happens only when the component mounts i will actually get a infinite loop so let me showcase that let me remove that dependency array let me save it let's navigate to the browser and then more specifically we're looking for the network tab and notice over here notice the amount of requests that are we making so why is that happening well first let me go back and actually add here a empty array let's save it and then the reason why is that happening is because we need to remember that when it comes to use state every time we change the value of the year state we trigger re-render so now let's go step by step when it comes to our fetch functionality on the initial render when the component mounts we invoke use effect correct now instead of that use effect the callback function we fetch data and change their values for the meals so there is initial render and instead of the fetch meals we change the value for the meals state value now what happens when we change the value we trigger another render we trigger re-render now what happens in that next render well we repeat the steps essentially we repeat the steps 2 and 3 in here so since we triggered that re-render inside of the fetch data we go back to the step 2 and then step 3. that's why you'll have so many requests and eventually the browser will run out of those requests and effectively crash because you have infinite loop since we trigger rerender when we change the value of the state variable that's why we need to be very careful when we set up the use effect and refresh data keep in mind if you just have simply console log then of course it's not going to happen because you're not triggering that re-render but if inside of the fetch data or fetch meals whatever fetch function you have if inside of that function you change the state value which is our case of course then yes you need to make sure that there is a dependency array and if you're placing any values inside of it you need to have a clear idea when this callback function is going to be invoked otherwise you're risking setting up the infinite loop and then like i said eventually your browser will crash and the same goes if you'll invoke the function inside of the use effect so this is the question that i get quite often where students say hey but why do we need use effect why we can't just move fetch meals outside of the use effect well let's see you'll pretty much see the same result again let me save and let me navigate back and notice again we get tons and tons and tons of requests because we have infinite loop that's why you always always want to fetch data as of now of course things might change but at the moment in react you always always want to fetch data inside of the user and you want to make sure that you start at least with the empty dependency array and then eventually as you add values that you have a good understanding when this callback function is going to be invoked because remember once we start adding values over here we'll invoke this callback function and all the code inside of it once the values that we add there change and while we're still working with the meals let's also set up a loading check as well as empty meals effectively if we don't get any data back from the api first i guess let's start with loading you see when it comes to data fetching effectively it doesn't happen instantly because it is a synchronous operation now of course it happens fast meaning in the human time it's fast but it still takes a little bit time in the computer time and we can clearly see that if we navigate to a network tab and if we slow down the network so in my case i'm going to go with fast 3g and you'll notice that initially there's nothing on the screen we just have that empty array and only after time we actually display those meals now in my opinion a better setup is if we have some kind of loading condition where essentially we display something on the screen and to showcase that i'm going to navigate to a complete project and you'll notice there that we'll have this loading dot dot dot so effectively while we're getting the data we're just displaying to a user that hey we're loading it and then once we get the data then we display the emails and the steps in order to set it up are following first set up a state variable by the name of loading at least that's going to be my name and default value is going to be false now in the fetch meals the first thing you want to do is set loading to true so as we start fetching meals we set loading to true then the last thing that we want to do in the fetch meals is set loading to false so once we're done fetching data regardless whether we get back the data or there's an error we want to set loading to false and then we want to add that loading state variable to a value prop basically we want to pass it down to our application in the meals jsx we want to grab the loading variable and we want to set up the condition now it needs to be before our current return so if loading is true then we want to return loading dot dot and then once the loading is set back to false then essentially we display the array of meals and as far as my solution it's going to look something like this or like i said there's going to be a state variable in my case i'm going to call this loading and of course there's also going to be a set lowering function the initial value is going to be false and the notice in the fetch meals the first thing that i do will set loading to true so that's when we start loading the data and regardless whether we're successful or there's an error we sit loading back to false we pass down loading to the entire application so essentially we add it to a value prop and then in the meals i destructure it i say hey grab me loading and right before our current return i go if loading is true so while we're loading what we want to display we want to display section and yes we do need to add a little bit of style so i'm going to set it up as class name section in there i'll set up a heading 4 with the text of loading and essentially that's it and of course after that we have our return so the idea is that while we're loading this is what we display on the screen so now let me set this one up or first in the context i want to create that state value and i'll purposely set it up before meals that's just my preference so const and then loading then we also want to go with set loading now the initial value is use state and we want to set it equal to false then in the fetch meals let me call it so set loading is equal to true now let's copy and paste and then at the very end of the logic let me just set it up here as false so we're done with the loading then we want to pass this one down so let's pass in the loading as well and then in the meals we wanted to structure it so let me navigate back to the meals jsx and before or after the meals it doesn't really matter i want to grab the loading and before i return the array of items before i return my cards that have the info about the meal i also want to set up the condition for loading so if i'm loading there's going to be a different return and as a result we'll have that loading displayed while we're fetching the data so near like i said there's going to be a section with the class name of section so we'll have to add a little bit of css as well so let's go here with return then section let's add a class name right away in this case the class name will be section and then inside of it we're going to go with a heading 4 and the text of loading data so this is true this return will be displayed and then once this one is set to false then we'll render the array of meals so let's try this out where first i'm going to navigate to a browser let me refresh and if everything is correct we should see that loading displayed on the screen now we still do need to add css so let me just see whether the functionality works and if everything is correct then we'll proceed to css yep i can see the loading displayed and i'll let me navigate back to our application we want to look for app css and we'll have to grab some styles from the section center so that's already a modal i want to look for section center and before the section center i'll create a section class and we'll grab some values here from the section center so we want to take padding with max width as well as the margin and effectively there are two ways how you can set it up so you can just copy and paste the styles or there's another approach if you want to save some lines of code so if you are interested in the other setup we can also add a comma here go with section and center so now we're reusing these styles for both of these classes and then when it comes to section center we just add the extra styles that are not included over here so that's another way how we can set up the logic the result is going to be exactly the same where now we'll have a proper section and in there we'll have that loading condition so before we display the array of meals we'll also display the heading 4 with the text of data.loading and as i said we'll use an extremely similar setup for the condition if we get back no data from the api and i think at this point we can just go back to no throttling and up next let's handle the case if we don't get back any items from the api and i think the easiest way to showcase that is just by navigating to and notice at the moment we're using this all meals url and since we have a search time of a of course it returns some data but what if i type some gibberish over here let's say i'm going to go with five a's let me save it and then if we take a look at the meals app i mean don't see anything on the screen why well because we don't get back any data and the reason for that is because if we take a look at the api we can see that yes if the search matches some results we get back meals array but if the search that we type doesn't match any of the meals then we get back meals as now and if you want to see that just navigate to the api copy the url and just add some gibberish after the text they provided so if i just add s you'll notice that we have here meals no and we need to handle that case especially because eventually there will be a search input so the user will be able to type the search term and we want to display if the search term did not match any of the meals in the api as far as the setup let me find the readme here it's gonna go like this again i'll have to scroll down a little bit we want to go with fetch meals and in the case of success so in the try block we want to check if data meals is truthy basically if it's an array it's going to be evaluated to true in the if condition if it's equal to null then of course it's going to be false if it returns a true basically if it has some value only then we want to go with set meals and then data meals so at the moment we're setting pretty much our state variable regardless but we want to change it we want to set up if else condition and only if data meals returns true then we want to set the state meals as data meals otherwise we want to set it equal to an empty array in the state and then in the meals gsx we want to check if the length is less than one meaning we're checking for empty array and if that's the case again we want to return a section and in there i'll just type some error text now we want to place them in between the loading and the current return again this is very important because we start with loading then we want to display the error if it's there and then we want to return the list off cards and as far as my solution in the try block i'm going to set up if else in here i'll check if data means returns true if it's evaluated to true if that's the case then i'm going to go with set and data meals and if it's false then i'm going to go with set meals and then pass in empty array and then we don't need to pass anything down we're already passing down the meals in the value but in the meals gsx we want to add another condition where we're checking length of the meals if it's less than one same deal we want to return a section and in there we just want to provide some error code and most likely i'll copy this one since i'm too lazy to type it from the scratch but i'm going to worry about it once we get there so first let me showcase how we can also work with multiple files so if we click on this plus we can pick which file we want to display in my case i'm going to go with context and i also want to display of the emails one because that's the current file that we're working in and then back in the context like i said we just want to set up the if and else condition we're doing that in the try block so technically it's not going to be an hour since the api returns a status code of 200 which means that the request was successful it's just there's no data to return so in here let's go with if and then data meals if it's true then we'll set our state variable equal to that if not then we'll go with set meals and we'll just set it as a empty array then let's keep on moving and we want to go to the meals of course and here let's add that second condition we'll say if and then meals length is less than one what do we want to do well we want to basically return a text we just want to change the value over here so let me quickly run back to the readme and i'll grab these values so in here in the meals this is what we want to return so copy and paste and we are good to go so now let's try it out where i'm going to navigate to the application and if everything is correct if you didn't change the search term back to something that returned some items we should see this error message on the screen so now i want to navigate back to the context one and here let's just fix it where i'm going to go back to a now eventually this will be dynamic again that is going to be the case once we add the search input so at the moment once we fix yep everything is correct again we have an array of meals and up next let's work on the search component so in here user will be able to type the search term and if the term matches any meals in the database of course they will be rendered on the screen and also there's this option of clicking on surprise me where we fetch a random meal from the api and we'll start with the structure so first let's just get something on the screen and then we'll worry about the functionality so in the search component the search jsx import use state and use global context now please keep in mind they're not coming from the same place so one is coming from react and the second one is coming from our context then we want to set up a return and don't worry about the css yes it's not going to look pretty but we'll go with header we'll add a class of search container which of course eventually will style in the header there's going to be a form and inside of the form we'll have the input with form input class type text and then two buttons so right after the input we'll have two buttons one with class of btn and type of submit and the second one with the classes of ptm btn hipster and type btn the last thing that i actually forgot to mention over here in the app jsx we want to uncomment this correct so in the app.jsx display search component and once you're ready to see my solution proceed to the next video okay and i think i'm going to start actually with the last step so first i want to go to app.jsx and i want to remove that comment so let me just remove the code and now we should see a search component yep awesome then in the search let's start by importing both of those things the use state and use global context so first let's start with import use state and that one is equal to react so basically it's coming from react then the second one is use global context which is coming from our own context so dot or i'm sorry two dots and then we're setting up the context and then like i said as far as the return we're gonna go with header we'll add right away a class of search container so search container and then inside of it we want to go with the forum so as you can see this is an error it should be header here then let's set up that form component sorry element i guess more properly it's not going to have a class but we will have the input inside of it we'll set the type text and i'll also right away add the placeholder now technically you don't have to but i'm going to go with type then favorite and meal and also we want to add a class name and this is going to be form input let's close it and then we want to set up those two buttons so let's go here with button then type will be submit and as far as the text i'm just going to go here with search and also i want to add a class and it's going to be btn now copy and paste and i'm just going to add btn hipster the type will be good old button so go here with button and as far as the text i think we're gonna go here with surprise me so that should do it for the general structure now let me take a look yep and as you can see we've got a input with two buttons now don't worry we'll work on styles in the next video and the reason why the buttons are styled because the btn classes are already in the global css all right and up next let's style the search component since we have the structure in place and i guess i'm going to start by just changing these files around where first i want to open up a new one and this is going to be app css and then instead of the meals of course this will be a search since this is where we'll do all of our work so as far as the app css we have the mono okay that's good we already styled the meals we're not gonna work with favorites we'll work with search and this is the case where again i'll move this sucker here just so we can see what we're doing and let me close files for now and also maybe let's make this one a little bit smaller and then let's start by just styling the search container so let me grab the class here then i'll add some kind of height it's going to be 5 rems after that we want to go with background which will be equal to the state variable of white then we want to go with display flex so essentially we're setting this up as a flex box and we want to align all of them in the center so we go with align center and or i'm sorry align items line items and that will be equal to a center then we want to also place them in the center horizontally so we'll go with justify and content and that will be equal to a center so once this is saved we want to work with a form so basically now we styled the parent container now let's work with the form now it doesn't have a clash so just go with search container and look for the form element in here we'll add a width and you know what since the values will be exactly the same over here i'll just grab these two so this is going to be the width of container and the max width of container let's save this and then we'll make a form to be a flex parent as well so display flex and let's add a little bit of gap in between the items so 0.5 rms and then also let's go with flex wrap and then that one is equal to a wrap so if the size of the window gets smaller then of course we wrap it to the next line if you want to check it out just make it smaller and you'll see how we nicely wrap to a next line then we want to style the form input so let's go with search container then class of form input and here effectively we want to set up some kind of max with so this is not going to be bigger than in my case 200 pixels we also want to add a little bit of padding so let's go here with padding and then let's set it to 0.375 rms and then 0.75 rem's left and right so top bottom and then left and right let's add a border radius or radius and then this will be again a state variable so border radius and i also want to add the background as well as deep border so let's go with background that will be equal again to a state variable with a background color so this will match whatever i have for the body whatever gray color i have for the body it will be the same and then lastly we have a border here where we're going to go with one pixel solid and now i'm looking for one of the gray colors so far iphone hyphen gray and 200 like so so save it and then let's style the button and the placeholder so i mean we can i just style the placeholder first so in here let's say font family equals to inherit so now we're essentially inheriting the value and also let's add a different color so in this case it's going to be equal to bar and i think i'm going to go with gray 400 so just different shade of gray and then lastly let's style the button so we're going to go with search container and then class of btn and let's add a font size a little bit smaller so i'm going to go with font size and then 0.75 rams let's save it and we're pretty much done with the css so now we can jump back to the logic so let me just add a tab in a proper place and we'll continue with the handle submit and handle change logic okay so at the moment we have a good looking search component with the input as well as two buttons but there's no functionality and first i want to add handle change to the input so there's going to be a state value that is persisted between the renders and also i want to handle submit because at the moment you'll notice that once we click on the submit effectively we restart the entire application because that is the default behavior for the form and here are the steps that i'm going to take first create a text state variable and then we also want to set up two functions handle change and handle submit in the handle change we want to grab the event.target.value and please remember that by default it gets the event as a parameter and then we want to set that to a new text value so this one will have the set function and of course we want to pass whatever we get back over here into that set function now once we're done with that we want to add on change to the input and set it equal to the handle change and then when it comes to handle submit again we'll get back the object as a parameter and we'll just set up event prevent default otherwise again we'll have that default behavior where every time we'll click on submit we'll just refresh the application since the default behavior of the form is sending a post request and then we want to add on submit to a form element and set it equal to handle submit okay and as far as my solution so i've got text and set text the state value the initial value is equal to an empty string then i created handle change passed in the event since that's the parameter we get by default settext event.target value and the same deal with handle submit where event comes as a parameter and here i have event prevent default now i forgot to mention in the previous video that also for the input not only we want to set on change equals to a handle change but we also want to pass in the value so value prop and that is equal to a text so as a result we get the controlled input where every time we'll pass something in input the state will be updated and then as a result between the renders will also persist the state value and when it comes to the form we want to go on submit and pass the handle submit at the moment we don't have more logic but it will prevent that default behavior so let's set this one up where first i want to of course navigate back to the search component and then let's set up that state value so we're going to go here with const that's the whole purpose why we grab the use state so we're going to go here with text and set text and then that one will be equal to use state and we pass in the empty string then let's set up those two functions so const and i'm looking for the handle change now i'll grab the event object and then as far as the functionality every time we'll type something in input we're gonna go with set text and we'll pass in the event dot target dot value and also let's set up the handle submit so const handle submit and then same deal we grab the event object now the deal here is to prevent the default servant prevent and then default let's invoke it and now we just want to set up both functions so let's start i guess with a handle submit and we have a special prop for that we go with on submit is equal to a handle and submit the same deal here but we just need to add a value prop as well so let's start here with values equal to a text so now we're grabbing the state value and then on change so every time we'll type something in the input we'll also update the state value since we have the handle change so let's go with on change is equal to a handle change like so let's save it and let's take a look at the application so first let's check the submit notice now when we're submitting we're not performing a default action so we're not sending that post request so that's already a good start since we're not refreshing the application now the second thing is as we're typing we're actually persisting value in the state and if you don't believe me just navigate to the components and then if we navigate to a search component notice the state value and essentially as i'm going to be deleting the gibberish from the input i'll have the same result as my state value okay and now let's set up the search logic or essentially we can type something in the input click on submit and if there are no meals display will display error remember that's the one that we set up in the previous videos but if there are some meals that are matching the search term we nicely display them so now connect the search input with the meals that we are fetching and in order to do that in the context.js first we'll need to create a new state variable in my case i'm going to call this search term and the default value will be empty string then we right away want to combine the all meals url with the search term so prior to this we're all the time using all meals url but remember this is a hard-coded url so now i want you to remove that hard-coded value i believe it's a and then when we invoke fetch meals in the use effect i want you to combine all meals url with a search term then we also want to add search term to a use effect dependency array so every time that value changes we fetch new set of meals every single time then we want to pass the set search term because once we create the state value we also have the function that controls it and we want to pass this one down to entire application now of course in our case we'll grab it in the search jsx so grab this function and then in the handle submit if there's any text in the input then we want to set it as a value for the search term now optionally you can also set text back to empty value but that really comes down to the personal preference as far as my solution i created set search term and search term so that's the state value and that's the function that controls it and then in the use effect i passed in the template literal and i combined all meals url with the search term now keep in mind again we need to remove that hard-coded value of a in the all meals url and i also added search term to the dependency array so every time we'll change the value of the search term we'll perform a new fetch request and the new value of the search term is going to be used then we also want to pass set search term down to entire application so we need to add it to a value prop and then in the search jsx we wanted to structure it we already have use global context so we just grab it from use global context and then in the handle submit i want to check what is the value for the text if it's empty we're not going to do anything however if it has some value we can just go with set search term and pass in the text like i said optionally you can set it back to a empty string when it comes to the text but that really comes down to the preference so let's start in the context.jsx first i guess i want to remove that hard-coded value here in the all meals url so instead of a it's just going to be an empty value then we want to go with a search term search term and then comma set search term set search term and that was equal to a use state and we pass in a empty string then let's keep on moving we're not going to change anything in the fetch meals but we do want to refactor this one so like i said we're going to go with a template literal since now we'll combine both values all meals url with the search term so first let's access all meals url and second let's grab that search term search and term then we want to pass down the function that controls it so let's go with set search term and now let's navigate to the search jsx first we want to grab it so we're going to go here with const we're getting back the object and we'll invoke use global context and let's go here with set search term and now let's set up that condition so if there's any value in the text then we want to go with set search term and we want to pass in the text and optionally like i said i'll set back the text to a empty value so now let's navigate to the application and see what is the result so first let me refresh and let's take a look at the network so notice here how we're basically fetching without any kind of value for search and what's really cool that they do return some default meals that is already a awesome start and now let's try to submit the form so i have here the input i'm typing something and now i click on search now i can see that we set it back to an empty text so technically our functionality works but we're not performing a new request so let me quickly take a look here at the app provider and i can see that i have the value in the search term so now let's see why we're not invoking new fetch request and i think i know why so back in the context i didn't add the search term so this is what happens if we don't add this to a dependency array this will only run the first time on the initial render now in this case though if we add search term then we're good to go because now every time we'll change this value the state value will perform a new request now of course in this case we didn't get anything back so now let me go here and now notice these are going to be all the values with a and then if i type a b these are the values that we're going to get back now as i'm looking at it i think i rather just leave that text the state value for the input so let me quickly now get back over here and okay so this is optional this is up to you and i'm just going to remove it so in this case every time we type and we search for something we'll actually see what we just wrote and we'll be able to make basically modifications so in this case if i go with ad check it out these are the values that i'm getting back and successfully we have set up the search functionality okay and up next let's work on fetch random meal functionality so once the user clicks on the button surprisingly we want to fetch the random meal and here's my solution so in the context jsx i'm going to create fetch random meal and there there's going to be a fetch meals so the same function we already used before we just passed all meals url plus the search term in this case i'll just pass in the random meal url and then i'll pass it down to your entire application effectively i'll set it up in a value and then in the search jsx i will destructure it and for now so change this around actually in the following video because there's gonna be some bugs but for now i simply wanna invoke it once we click on a button so i'm going to set up a on click and i'll pass in fetch random meal and as far as the result it's going to look something like this notice we have all the meals and then once we click check it out we get our random meal so let's set this one up we're in the context.js let me keep on scrolling so i have my use effect um i think i'm gonna do it before the use effect and in here we'll just create that function now the name is really up to you in my case i'm going to go with fetch random meal that's a function and inside of it let's just go with fetch meals and then pass in random meal and url let's save it let's pass it down to the application so fetch random meal let's save that and then in the search we wanted to structure it so fetch random meal and probably at this point just copy and paste since it's gonna be faster and then where i have the surprise me button i'll add on click and we'll pass in the fetch random meal and now let's try it out so i'm gonna go here to the application click and yep we're getting the random meal and again the cool thing is that when it comes to the api the structure is the same yes we're getting only one meal but since it's set up in array we don't need to change anything here in the function in the fetch meals function we still get back to data and in there we have meals array and now we just set that meals right that one random meal equal to our meals state variable and then eventually of course we display it on a screen now there are some bugs and we'll fix them in next video but the general structure works yes we can fetch random meals once we click on the surprise me button so our basic functionality works as expected however like i mentioned at the end of the previous video we actually have a bug in our code and i think it's going to be easier to showcase it because i actually didn't pay attention that in the search jsx i still have the code to basically wipe the value and effectively the bug is following search term you know the one that we're using to pass it into the all meals url actually has the value and i actually want to wipe it so let me showcase the bug first let's imagine the user comes to application and we serve the meals that we get back if the search term is empty and let's say he or she searches for the meals with the search term of d okay awesome and then we go with surprise me so technically functionality works but if i take a look at the developer tools more specifically i'm looking for components and then the app provider notice here the value of d so that value is still here and that might be misleading since if the user comes here and types d notice nothing is changing why well because we only fetch new meals if the value changes and in our case we already have this d and let me just double check the name so we're looking for this search term so that's the one that's not changing now how we can fix that well what we could do in the search jsx we could set up a new function we can create handle random mule and in there we'll set this one to empty remember that's the one that we're using over here and we'll also set the set text to be empty and lastly we'll invoke the fetcher in the mill now there's gonna be another bug but first let's fix this and then we'll worry about that one so now i want to go to search jsx and like i said first i want to set up that handle random so before the return let's create another function so const handle random meal that's my function and here let's invoke a few things now in order to speed this up i'll just copy and paste so we have search term that one i want to set equal to an empty string the settext also is going to set it equal to an empty string and now i want to go with fetch and i believe it was random meal let's invoke this but now we want to change this around where it's not going to be fetch random meal we'll actually look for handle random meal let's pause that one and now notice that yes we nicely wipe out all the values but the problem is going to be that we set up another request and let me showcase that so again let's start from the scratch i'll just wipe it clean then i'll type d okay so we search for the meals then we go with the run the meal and technically everything works but i don't see the random meal now why is that well if we take a look at the network we can see that we're making two requests right now we have one for random and one for search now why is that well let's take a look at our code what are we doing here we're setting the search term back to nothing now why is that important well because we invoke this use effect every time this value changes so we fetch the random meal it's over here in the function but we also perform another fetch meals with the all meals url and here's the fix so first you want to set up another use effect in the context.jsx so this is going to serve the moment application loads at the moment application loads we get all males url with empty search them that's going to be again only when the application loads that's it now after that we'll set up another use effect and this is a good side note where you can have as many use effects as you want in your application you're not limited to one that's why i purposely fixed bug this way because i want to showcase that yes you can have multiple use effects now in the second use effect i actually want to check hey is there a value in the search term if not then just return what does that mean well that means that this functionality is not going to run now why is that important because if i'm not going to have this second use effect the first one then initially we're not going to get any meals because remember this is an empty value however now we fix both issues initially we get all meals url and then second every time we change the value we still check what is that search term if it's empty then nothing so that fixes our random meal bug so let's try this one out where in the context.jsx i have my first use effect and that's awesome we'll still have to add a little bit of code over there for now what we want to do is create another one and you know in order to speed this up i'm just going to copy and paste like so and here let's just remove the search term and rest of the functionality stays the same i mean technically we can actually remove the search term there's no need we can just go with all meals url and just to reiterate the value for the search term is empty but the cool thing is that the api still returns the emails and then in the second one we want to set up the condition where we want to go if there is no search term then we want to go with return and otherwise we want to call this and lastly in the search jsx i actually want to remove this one i want to leave the text that currently is displayed basically i want to display the search term so the user can see so let me navigate back again let me refresh notice how on the initial load we still display nicely all the meals okay that's awesome then let's say we're gonna go for the search term of f so we get the meals okay beautiful but once we click on surprise me first of all we get that one meal second if we take a look at the provider we'll see that this is empty so that actually matches whatever we have in input and lastly if we take a look at the network now we only have one request now we have only the random one awesome and with this in place now we can move on to the next step all right next let's work on the modal component and in the complete application it's going to look something like this where we can click on the image on one of the meals that we display effectively in the emails component check it out now we have that one specific meal and also we can click on one of the favorites one um it's also going to be displayed in modal and for now we'll just worry about rendering something on the screen because as we can see we don't even have the component and first i want to set up a return in the model jsx and yes we'll style these classes right away and you'll see in a second why because they are effectively responsible for most of the css features so the dark background and then the white color and all that so yes we'll basically style them first then i want to set up a state variable in the context.jsx i'm going to call this show model and set show model and the initial value is going to be false now yes eventually we'll control this once we click on the image here or on the image in the favorites but for now i just want to showcase how the logic is going to work and we want to pass this down the show model one and then in the app jsx remember we're not even rendering the model yet but we want to right away grab the show model now don't worry about the favorites actually this is an extra which shouldn't be in your readme so that one is coming up but in here we want to grab show model and of course we first need to import the use global context invoke it get the show model and display model only only if the value is true and for now we'll just toggle it manually just so you can see the basic functionality so first let me go to a search and let me change this around to a modal and then as far as the return like i said i'm gonna go with few classes that will style first and you know what also let's grab that use context let me see over here this sucker over here since we'll use it in multiple places we might as well copy it here so copy and paste so use global context eventually we will actually invoke it but not for now and let's go with aside then let's add a class name last name now will be equal to modal overlay as a signal that's the dark background that you see in the complete application and there's also tiny bug over here this should be a side and then inside of this element we're going to go with div and then we'll have a class name of modal container model container so that's the div with the white background where we'll see the image and all of the data about the meal and for now let's just say here a roll container or you know temporarily i'll add a heading 1 and i'll say modal container just so we can see it better all right so let's save this and then we want to go to the context we want to create that state variable i guess i'm going to do it right after the search term over here so const we're looking for show model then set show model so this is the function that we use to call it programmatically and as far as the initial value you know it eventually it will be false but since i want to showcase the modal i'll set it temporarily equal to true let's keep on moving then we want to pass down the show show model and we want to jump back to app jsx first we want to get the global one and again this is going to be the case where i'll just copy and paste i don't want to type it from the scratch so model here we just need to change the path of course so app jsx import and then it's in the same folder so it's only one dot then we want to grab the value the show model here so const show model and then that one is equal to huge global context let's invoke that and then where we have the modal at the moment we have comment around so we want to uncomment that but we will right away want to set up the condition we want to say only if show modal is true then so that's the end operator then we display the model so let me place it here and now let's see what we have since the value is true we should see right away model and now let me switch back to the context because that's the file where we'll be setting up most of the logic let me go back over here notice i have the model container why well because the value is true if i change this around in the context and if i set it equal to false where it is where it is over here if i set it equal to false bam we cannot see the modal nothing so we don't display the model so that's the basic structure for the model where we have the boolean state true or false and depending on that value we display or hide the model okay and up next let's work on the css so our modal actually looks more like this than what we have right now so at the moment we just have a heading one and yes i know i've said this already twenty thousand times but let me repeat one more where if you copied the entire css you don't need to do anything you can switch to a next video in my case i'm going to open up a new file and somewhere here i'm actually looking for the css one and the app.css is not coming up in my reset ones but we can always search for it like so and then let's keep on moving and if i remember correctly modal was the last one so let's work on those two classes and let me set it side by side right away like so and here let's first worry about the modal overlay so that's that dark background that we have the class is modal over lay and here let's set up position first of all fixed so it's going to be taken out of the normal flow then we right away need to add the coordinates in my case i'm gonna go with top zero and left zero so it's going to be all the way on the top on the left hand side then i want to set it width to be 100 and height to be 100 so effectively i want to take it up all of the screen with 100 and height also 100 and then we want to go with some kind of background so that's where we'll set up that dark background bang on property and i'm just going to go with rgba because the opacity value is a cool one that allows us to control how dark it is so for example in your case if you want it lighter then just change the last value the opacity in my case i'm going to go with 0.85 let me add here a colon so that's our modal and then effectively when it comes to the overlay i want to set it as css grid and place the items meaning our container in the center so i want my overlay to take up all of the screen but the items i want in the center that's why right after the background we'll set it up as display grid we'll also use the place items and center and as you know this is a cool property that allows us to combine align items as well as the justify content so instead of writing two lines of code you can write one then transition and i guess we'll have to write it here so transition that just can signals that the change is going to happen over time and we're going to go with var and then transition just this variable and then lastly we want to add the z index just in case there's some other elements that are taken out of the flow and we just want to place it on top of them so arbitrarily i'm just gonna go with hundred and now let's work on that model container and as you can see we already have the text technically in the center so this should give us a good idea how it's going to look like now let me select the class model container i'm going to go with width of 80 percent of the screen width and you know what let me add right away a background because it's going to be easier to see and we're going to go with the white so now we should see our model container then right after the width i'm going to go with max width so on a small screen it's always going to be 80 percent of the screen width now i don't want that model to be bigger than 800 pixels as far as the width now height always is going to be 80 view widths i'm sorry view height that's more proper so view height and then i know that the content is actually going to overflow i mean again if we take a look at this notice in here technically it didn't but if we take a look at the big mac notice so there is an image on the top and there's also the cooking instructions so now for sure that the content inside of it will overflow and that's why we need to go with overflow and just decide how we want to deal with that in my case i'm going to go with scroll and lastly let's go with that border radius just so we can have those nice rounded corners so border radius and we'll set it equal to var and then css variable with the value of poor radiators and we're pretty much good to go we have set our basic styles so now we can continue with the functionality beautiful and up next let's decide how we can pass the meal into the model so at the moment we just have a dummy content but of course eventually we'll have the functionality where once we click on any of the meals that we have here or any of the meals that we have in the favorite the data about the meal is going to be passed into a model and will correctly display and as far as the setup first i will create a selected meal and set selected meal in the context.js so again we're creating new state variable and initial value is going to be no then we want to set up a function that is going to be looking for two things the miele and also is it a favorite meal now we don't need to worry about this parameter for now we don't have the logic for it yet but eventually yes we need to keep in mind that we have two places where we have meals we have the favorites and also we have just a regular list so yes there's going to be a flag whether it's coming from favorites or is just a regular meal and then we want to look for the meal using the find method and we want to look where in all the meals in our state variable so if we remember here we have meals and then once we fetch those meals we set meals equal to whatever is the array we're getting back from the api correct so now we want to grab the meal id then we want to use it to get the meal in the array and we want to set it equal to our selected meal state variable and also we want to showcase the model now what was the function that was set show model then we want to make the select meal and selected meal available to rest of the application so we want to pass it into a value and then back in the meals we want to grab select meal so that's the function over here the select meal and then we want to invoke it once we click on the image so we want to add on click and pass in the id and i'll talk about why we need over here this arrow function again few things state variable the function we want to pass both of those values down so selected meal so this is what we're going to use in the model and select meal which we'll invoke in the meals so let's go step by step first let's create that state variable and in my case i'm going to call this selected meal so effectively what meal we have selected set selected meal now that is equal to use state and by default let's set it equal to no so by default it's not going to have any value but i also want to change this one around where it's going to be false so by default we're not going to display the model let's come up with that function and i think i'm going to do it right after the random one so let's create it const select meal and here the function is looking for two things for id meal effectively that is the meal id i'm just using the same property name as it comes from the api because that way it's going to be easier to understand at least in my opinion then we want to go with favorite meal which is a boolean value but at the moment we don't really care about it and we're going to go with let meal so initially it's nothing that value but we want to go with meal and then meals fine now why we're going the long way because there's going to be an if condition so for now yes there's only one possibility where essentially we'll just use this id meal and we'll get the meal from our array again we'll get the meal from our meals array so let's go with find method and pass in the callback function i'll reference each and every meal there as meal and i'll say get me the meal whose id matches the id meal basically whose property is exactly the same so id meal is equal to id meal that we're passing in and then let's set up two more functions first let's go with set selected meal so this is the meal display in a modal that's where we pass this value and second we want to open the model correct so set show model and let's set it equal to true let's save that and now we want to pass down two things we want to pass down the selected meal and we want to pass down the select meal so let's look for the value selected selected meal and we also want to go with select meal and now we want to navigate to bum bum bum bum css even though we will use it later we want to navigate to the meals we want to grab select meal and then let's look for the image now let's shall we destructure the idemill correct when we iterate over our so now we can just grab this value and pass it into a function now let me first showcase what is going to happen essentially if we don't pass in the callback function because this is the question that i pretty much get all the time as far as react so let's go over here and let's say select meal and let's pass in the id meal like so let me save it and you know what for time being let me just add a console log just so we can see that we have called this function because effectively it's going to be invoked right away and that's not what we want we want to invoke it only when we click on email so let me try here uh hello let's see let me save the application which you'll notice that first of all we'll open up the model right from the get go because that's the logic and also we'll have these 25 meals now why do we have that well simply because like i keep saying if we set up the function this way we invoke it right away so the moment application loads the moment we display the meals we invoke it but that's not what we want to do we want to invoke it only once we have clicked on it and the solution for that is following where we want to go with a arrow function and then we want to set up this function as the return from the arrow function and as a result you'll notice that everything works as expected so we get our array of meals and only once we click on it we shut that selected meal again the reason why i'm spending so much time on this because this is probably top three questions i get why we set up this arrow function simply because if you don't have the arrow function you invoke it right away and that's not what you want to do you want to set this one up as a return from the arrow function so initially this arrow function runs returns this function and then we invoke select meal passing the id only only once we click on the image let me also do one more log in this case i'm going to go with id email just so we can see that we're passing in that value so let me go back to my application first of all you'll notice that we'll display the modal because remember we go with set show model and we set it equal to true so bam check it out we right away display them all and also we'll have here the id now we don't have a way how we can close the model so that's why i mean it's just going to be sitting there right now but lastly in this video i just want to showcase that if you go to components you should also see this one what is this that's the meal that we selected how do i know that well because the idea is exactly the same so that's the state value the selected meal one initially it was no and now it's actually equal to the meal that we selected all right and up next let's render the meal that we have selected and also let's set up the close model functionality now dcss will add in the following video so if it looks somewhat ugly during this video i mean it is what it is the most important thing uh is to get the data on the screen so i want to showcase which meal we have selected and i also want to close the model and then we'll worry about the styles so first in the context.jsx and for some reason i have context and most likely i'll have to fix it in multiple places but again that's my problem we want to create close model and in here we'll go with set show model and we'll set it equal to false now we'll pass it down to a application so add that into the value and then in the modal we want to grab two things we want to grab selected meal like i mentioned in the previous video so select meal we utilized it in the meals now selected meal will utilize it in a modal so grab both of those things close model and selected meal we'll destructure again a bunch of properties out of it so image title instructions as well as the original source and then we'll work on our return and all the way in the bottom there's going to be a button that allows us to close the model so let's start working on that one i guess first let's go to a context one and we want to create the closed model function so again i'm going to do it before use effects and it's really up to you where you want to do it so close model and as i said yes of course you can pass in set show model but i always prefer just setting up the function makes a bit more sense to me so set show model we want to pass in as false of course because we're closing the model let's add a comma close model and we're already passing rest of the stuff so we don't need to worry about it after that we want to go to a model and we want to invoke that use global context and we want to grab two things we want to get the selected meal again this is the meal that we want to display this is the meal that we set once we click on those images and second we want to grab close and modal and that is equal to use global context let's invoke that and we're good to go then let's destructure it because we actually want to display it and you know what let me just mess around a little bit let's set up a button here just so we can close it let's write closed and let's set up on click now in this case we don't need to invoke it meaning as a arrow function we can simply go with close model since this is a reference again we're not invoking when you're invoking that's when you need to set it up as an arrow function now we don't invoke we pass it as a reference and then you know what let me just display the title just so we can see that we're getting that exact meal and this is also something that i suggest doing when you're building the application try to do it step by step um if you'll set a bunch of logic and then it turns out that you have a bug somewhere else this is going to be very painful to go and pack so that's why i always like to do it step by step where first i just display the title see that i'm actually getting the correct meals and then i proceed to the structure of more properties so in here i simply want to go with selected meal so for time being i'm not going to structure it i'm just going to look for the entire object and we're going to go with dot and i believe the value is sdr meal and now let's try it out what do we have let me refresh just so everything is up to date yep that's the meal that i selected i can clearly see that and i can close the model and the next one next one and i can clearly see that my initial functionality works so now it's just an easy part where we wanted to structure it and that is coming from selected meal and then one by one let's grab those properties again we do want to get the image so this one is that annoying one thumbnail that is equal to an image now sdr meal equals to title in my case then instructions and as i say not again if you want to see all the properties that are there in the object either you can log it here in the model or you can simply go to developer tools more specifically to our components and analyze it so let's go here with instructions set it equal to text and then lastly source and effectively this is the original uh kind of resource so let's keep moving we're not gonna have the heading one here and actually button the button is going to be another div so for now let's just leave it the way it is so first in the container we want to set up a image so let's go with img source and then image and i'll say not yes i know that i'm not setting up the alternative attributes and maybe you know let's change it let's pass here the title and you can also do that in the meals my apologies i forgot when i was setting up the meals so let's go here with a class names and we want to set up img and modal img so this is the global class and this is the class which we're going to style in the following video then right after the image we want to set up another div with a class name of modal content modal content and we want to place that button inside of it yes it's going to be all the way on the bottom but different div then let's go with heading 4 we're going to look for the title after that we want to go with a paragraph and we're just going to say cooking instructions and then let's set up another paragraph with a text so let's look for the text over here and lastly we have that original source so for that we're going to go with an href attribute we'll pass in source and i also want to open it up in a new browser tab so therefore i'm going to go with target and then underscore black again this is effectively a html attribute so let's pass here the value for our link and that is going to be original source and let's see how bad the css looks let me navigate here again i'm going to refresh so everything is up to date and then let me click on this one and there is a issue okay so select meal is not defined okay that's interesting so select meal is not defined modal jsx probably i just messed it up as far as the name so let me go here and yeah of course it's selected meal my bad see how easy it is to make a silly mistake let's try one more time and yeah i mean it looks ugly correct but as long as we can see all of the items so the image the title the cooking instructions as well as the original source we're good to go because we'll set up the styles in the following video and as far as that target blank check it out once we click on it we navigate to the original resource essentially where the recipe is coming from not i also noticed that in a context i still have that log so let me remove that sucker and just like that we're done with the functionality of displaying the selected meal as well as closing the model so up next let's style our model so it looks a bit more presentable okay and up next let's work on the styles so at the moment we have all the functionality but it definitely can look better and i'm going to start by navigating to the app css yep over here we're looking for the model which i believe was the last one and we want to style the image first then let me grab it here just so we can see right away the result and i'm going to start by targeting the image the modal img and i want to add some kind of height so it's always going to be 15 rams now of course that is up to you you can make it smaller bigger uh that is essentially irrelevant then we want to add the borders for the image because at the moment we just have for the container so in my case i'm going to look for those properties here so board top left and border top right let's copy and paste that essentially it's going to be faster then for a modal content first let's select the class then let's add a padding one rem's top bottom and then 1.5 left and right then for the content effectively for those paragraphs i want to add the great color model content and then paragraph and that is going to be gray 600 that's the value color var css variable gray and then we're looking for 600 after that we want to style the link so this one over here the original source and also the close button and you know what i think i think there's a button missing and yep so it's actually btn b10 hipster and close model i didn't add those classes my apologies so let me navigate back so class name we're gonna go with btn btn hipster and then we'll add close and btn let's save that that should do it let me click yep that's the button right now and then back in the css we want to target the button you want to look for that closed model i believe or close btn the one that i basically just set up and we want to add the background color different so let's go with close btn and we're going to go with background and we're going to set it as a red hyphen and dark and then after that let's go with color and we're going to set it equal to a white one all right so that should do it for the button and then lastly let's worry about that link so that's going to be under modal content and link in here let's go with display block because i want to start in the new line i want to set some kind of color in my case i'm going to go with primary and 500 then we want to add a little bit of margin in the bottom so my case i think i'm going to go with 1rms margin bottom equals to 1 rm then we have text decoration which will set it equal to the underline text decoration and that's equal to a underline let's save it yep looks about right and then lastly we just want to add a little bit of transition since there's going to be a hover effect as well so first let me select here let me add hover so as we're hovering we want to set the color equal to a black and then let's add that transition and that one will be equal to a css variable with the same name transition and once we set the styles we're pretty much done with the model and up next we're going to work on the favorites component and as far as the favorites we want to start in the context jsx we want to set up a new state variable by the name of favorites we also have a function set favorite and for timing is going to be empty array eventually we'll set up the local storage so once the application loads we'll check the local storage first but for now let's not worry about it we will set up two functions one is going to be add to favorites which again will look for id meal basically the email id then we'll use that id to find a meal in the meals array after that check whether it's already in the favorites so essentially if i have that meal and a favorite i don't want to add it one more time and if that's the case then we'll just return so nothing is going to happen if not if it's not in the favorites then we'll spread out the current values the favorites one and we'll add that extra meal so we create a new array we spread out the existing values and we add that extra meal and then we use the set function to actually add the new array as our value so we have the current value and this is the new one and while we're on topic right away let's also create a remove from favorites so this one again is going to be looking for id meal and we'll invoke it from the favorites same deal however in this case we right away look in the favorites and we just say look return only the meals whose id does not match the id meal that we're passing and again we go with updated favorites so now we use set favorites and again we pass in the updated favorites so all the time we just change the values in the array and we set that array as our new state variable we want to pass both of them down to your entire application so pass both of them in the value and for now in this video we'll just worry about adding to the favorites so we'll have to destructure it in the meals and then notice how it's exactly the same as select meal why because again we're passing in the id meal so hopefully you remember why we're setting up that arrow function so here we have that like button and every time i click on that button we'll add meal to the favorite and i guess i'm going to start by setting up that state variable i believe that's going to be actually our last one if i'm not mistaken so favorites then set favorites and we'll use use state then like i said before for now it's just going to be empty array let's keep on moving and i'll set up both of these functions here const add two favorites it's going to be a function and it's going to be looking for one thing and one thing only the meal id which i'm going to name id meal just because that's the name of the property so i think it's less confusing copy and paste and we want to go with the remove remove from favorites after that let's set up the logic so like i said first we want to get that meal from the meals state variables const meal and that one is equal to meals find and let's pass in the callback function i'll reference each and every meal as a meal parameter and i'll say if meal id meal matches the id so the parameter we're passing in if it matches the meal at the property then good then get me that after that we want to check if it's already in the favorites so const and then already favorite and that will be equal to favorites and we're gonna go with find check for meal and same deal basically if the id matches then this is going to be true so in here we can kind of cheat a little bit where i'm going to grab the logic again it's the same deal keep in mind that once we get this meal and we pass it into array the structure is going to be exactly the same that's why we can do that uh now let's set up the condition if it's true if already favorite evaluates to true in this case then i want to return why because like i mentioned i don't want to add it multiple times to a favorites i mean if it's already there then i'm good to go so that's why we can click all day long and nothing is going to happen that's exactly the result i'm looking for and then lastly if that's not the case then javascript is going to keep on reading the code and therefore we'll create this array update favorites and now will be equal to a new array let's spread out all the values in the state in the state variable let's add that meal sucker over here and then let's go with set favorites and let's pass in update favorites now eventually yes there's going to be a local storage but for now we're not gonna worry about it so we're gonna go with updated you know what i need to actually fix this updated and then favorites all right that's good so now let's set up the logic where we remove from the favorites and we'll do that by again creating a new variable updated and then favorites and we're gonna go with favorite state value and we will use the filter method and we'll check if the item id mail property does not match the id that we're passing then we'll return it into our new array so essentially we'll just exclude the item whose id matches and as a result we'll be able to remove the meals from the favorites area like so we click and we're good to go and this is going to be the case where again we want to pass in the callback function and we want to go with meal and as i said i need to set it up here as a param meal and if meal id meal does not so this is the case where we're looking for the items whose id does not match what we're passing then we return in that new array and now we want to do the same thing over here we want to go with set favorites and then passing updated favorites and then let's pass both those things down so it was add to favorites and it was also removed from favorite and once we have this one in place we just want to go to meals and then we want to structure it of course so say add to favorites and now let's keep on moving and we're looking for the light button so here we want to add again on click and yes i'll repeat one more time since we invoked a function basically there's no other way for us to get the id email we just have to pass it in and since we invoke it yes we need to set up the arrow function so let's go here let's say on click um set up the arrow function first let's see i think i have a mistake here and then we will invoke add to favorites and then let's pass in the id meal and if everything is correct uh we'll definitely see that in the components essentially in our developer tools but if you want to double check that you can always console.log so let me go back to the context let me find this one and i'll just log for time being and i'm going to pass in id meal so let's try it out i'm going to navigate to my application um i mean you can pick any of the meals and then just click on like button and we should see in the console some logs and also like i said if we check the dev tools either in the app provider we should see yep notice over here so that's the favorites array effectively every time we'll click on it we'll add the item so let me try here notice now i have three of them then this one is already here i guess that's why i don't see it and then notice every time we click on the item we add it to the favorites all right and now we just need to worry about how we can render it on the screen and as a quick sign up if you want to make your code more performant you can refactor meal below the return so essentially if you move the meal below the return now you'll see that we only search for the meal twice in the favorites and in the meals if we already know that is not in the favorites since we know that if the meal is in favorites we return regardless so if it's not in the favorites yes then we go to meals we get the meal and then we add it to the updated and you know the rest all right next let's worry about rendering the favorites and the first thing we want to do in the app jsx we want to grab the favorite state variable and we want to check the length and i only want to render favorites if the length is bigger than zero it's an array so we can always check the length and only if it's bigger than zero then we render the favorites and effectively the result is going to be following if i have no items in the favorites then we're not rendering the component all together and once we have that set up in place essentially we want to grab favorites select meal and remove from favorites in the favorites component so this is an array that we're going to render so if i add it here norrish that's going to be our component that's our array and then we want to grab the select meal because like i mentioned previously yes we'll be able to open up a model from the favorites as well now there is a gotcha but we'll worry about it later now we just want to grab this select meal and then we want to also grab remove from favorites so that's the remove button that we can invoke over here um for now we'll just set up the return where we'll have some heading 5 as well as we'll iterate over the items and then in the following video i'll worry about the css again the result after this video probably is going to be somewhat ugly so let's start cracking and i think i'm going to go to app jsx first and i want to grab the favorites as well again that's my array and i want to check the length and only if i have some items in there then i want to render the favorites component let me go favorites and as i say not keep in mind that every time you refresh it we'll start from zero from empty array simply because we are not we're not using the local storage yet so let's go here with favorites and then let's check the length right away length and if it's bigger than zero then we want to render the favorites so let me add the component in the expression and we're good to go and we can actually quickly test it so let me go to my application refresh and it looks like i have an error it says here that we cannot read the properties of undefined and i think it's because i didn't pass it down in the previous video my band so let me go here in the context jsx let me add the favorites array so we also want to pass that one down and now once we refresh we should be good to go so at the moment we don't see anything again it is empty array but once we click on the like button we should see the favorites component because now we have some kind of value in there and let me go back to my context.jsx i think i'll remove this one for now the id and then we want to navigate to the favorites that's the component then i guess i'm just going to start by again grabbing that use global context so let me look for favorites i mean here let's set it up since we'll grab a bunch of values from the context and we'll start by setting up the structure so const we're looking for favorites then we also want to grab the select meal again that is coming up for now we're not going to worry about it and we want to remove from favorites hopefully that one i added to the context.jsx so use global context let's invoke that and now let's set up the return it's going to be a section we'll add a class name of favorites last name and set up equal to my favorites then we want to rename the closing tag so this is going to be a section inside of the section let's go with div so let's set up the div and in here let's add a class of class name first of all and then we're gonna go with favorites and content then inside of the div let's go with heading five and we're gonna go with favorites and then let's iterate over that list however we'll place it in the div so they have class name and we're going to go with favorites and container and instead of div let's iterate over that array so favorites array then we'll call the map and we'll set up the callback function i'll reference each meal as an item and then as far as the return um we want to go with constant we wanted the structure again how do i know that it's there because we're passing that entire object to array so i know that the structure is going to be exactly the same again what we're looking for we want to get the meal and we want to get the image that's all so in this component it's not much and in this case i'll rename it to an image and that is equal to an item then we want to return and we're going to go with div we need to pass in the key prop and in that case it's going to be equal to id meal then we want to set up a class name here class name and that one will be equal to a favorite item item and then instead of this dividend by the way i need to add the closing one inside of this div we first want to display the image and then we want to go with the button that removes that item from the array so let's start with img source will go with image again that's the alias that we just set up then let's add a class name class name and that one is equal to a favorites and then img and also img so global image class and then the favorite image class and lastly let's set up that button we'll add a class name and that one will be equal to a remove btn so this is the case we're not going to add that global class we'll just set up a class 4d favorites and then inside of the button let's just type remove and we need to add the functionality correct so again we go with on click and this time i'm not going to repeat why we use the arrow function please we'll watch the previous videos where we initially set it up so let's go here we remove and then favorites so let me set up the proper name here remove from favorites and let's pass in that id meal and once we're done typing out the return we can take a look at the application again i can guarantee you it's going to be somewhat ugly so let me click here and notice that's our giant image and then we also have that removed so if we add another one then yep it's exactly the same thing and now if we click on remove we can remove from the favorites so our next step is going to be to set up the styles so it looks more presentable like this and as far as the css let's navigate to your app css and all the way no actually no not in the bottom i have model in the bottom we want to set it up here between the meals and search first we want to grab the main container and let me set up the files here as well and we're gonna go with favorites let's add a background and we're gonna go with black one now of course keep in mind that we're not gonna be able to see so maybe um you know what either we can add a favorite just so we can see something or we can remove that condition i think i'm just going to add that meal and we should be good to go let's add a color here that one will be equal to white one then we want to go with batting one rem's top bottom left and right is going to be equal to zero we'll set up the favorites content and essentially i want to set up the width similarly to how we did for a search so let's go with favorites and content and i'm going to go somewhere and find the values essentially this is what i'm looking for so with max with as well as the margin 0 which in this case i don't have i'll have to add it so copy and paste and let's add margin zero auto so now we're placing nicely the content in the center then we want to work with the container so in this case we're looking for favorites and container noun will be equal to display flex and then gap so set up a little bit of distance in between the items and also go with flex wrap equals to wrap let's say that and as a result let me refresh it should look better and nope it's still quite big ah because of the image yeah my apologies we're not going to see anything as of yet but we do want to place everything in the center and when i say everything i'm actually talking about the button so favorite item and then we want to go with text align and center save that and now let's make that image quite small so favorite hyphen img and we're going to go with width 60 pixels so now it's going to be small i mean it should be favorite img and then let's check we have poor radius or radius 50 and for some reason i don't see the result let me try one more time again still it's massive so let me double check in the favorites so that should be favorite item and this is favorites mg maybe i'm selecting it wrong so apps yes yeah should be favorites img my bad so now notice we have image with border radius as well as the width so now it looks a little bit better then let's add a border and that one will be equal to 5 pixels solid and we're going to look for the css variable with a value of white and then let's also set up a cursor pointer since remember once we click eventually we'll add it to a model and now let's worry about the remove button so that one is the last thing we want to style essentially for the entire project so let's go with remove iphone btm and here we'll go with margin top and we'll set it equal to 0.25 rem then we want to go with background transparent we want to set the color equal to white so r and hyphen white after that we want to do the same thing with the border so let me copy this one let's just set the border so borders equal to transparent as well cursor is going to be equal to a pointer and what else what else what else we have transition since there's going to be a hover effect and also a font size so let's start with font size that will be equal to 0.5 rem so i'll basically make the text smaller and then after that we want to go with that transition so let's go with transition and the css variable with the same name so transition and let's quickly add the hover effect so we're looking for a move button and we want to change the color essentially as we're hovering so remove button hover and then let's just go with color bar and then red dark let's save it and now notice we have the favorites we can only see it if we add the meal and you know what i think you can place it already there and once we add to the list we have more meals if we want you can remove it as well and once i remove all the meals then of course we cannot see the component the favorites component okay and next let's refactor select meal see eventually i want to add the same logic to the image so every time we click on a favorites image we also display the meal in the model however we need to keep something in mind we have two arrays we have meals and we have the favorites and at the moment select meal is looking where it's looking in the meals so yes there's going to be some situations where the meal that you have in the favorites is also going to be displayed on the screen however if let's say i go with a random one now as you can see if you click on this meal and try to find it in meals it's not going to be there anymore so when we set up the select meal we also need to take an account that we'll call it in two places on the meals array and also in the favorites and therefore we have right now this favorite meal and effectively we just want to add the condition so we want to add the condition that if that is true so if we're calling it in the favorite meals then we simply want to look for a different array so then we want to look in the favorites one now if it's actually in the meals then of course we don't need to worry about it it's going to be right there in the meals array so therefore we'll set up the condition we'll say if every meal is true then we'll look in the favorites if not then we'll look in the meals and then in the favorites we already structured it we just need to invoke it we need to pass in the id meal so the meal id and also true because in this case we're calling it from the favorites i guess i'm going to start in the context and first i want to set up the logic i'll say if and then favorite meal you know if it's true then essentially the logic is going to be exactly the same the only difference is i'm looking in the favorites let's call it and we also want to place the second one in the else condition so now depending on the value of favorite meal we'll either check for the meal in the favorites or in the meals and now we just need to go to the favorites we already have select meal and we want to add the on click on the image now let's pass in the function first the arrow function and then we want to go with select meal then let's pass in the id so we're looking for id meal and second we'll pass in the true so yes we're calling this from the favorites and now let's check it out i'm gonna go to my application so notice now all the meals now i can add it to the favorites and even if my meals are right right now is different i can still display them in the model which is awesome all right and the last piece of functionality we want to add to this application is adding favorites to the local storage so at the moment everything works nice but the moment we refresh the application again we start from the scratch and instead we want to save to local storage every time we add item to the favorites and we can do that for both of them for add favorites and remove from favorites so when we want to add the item to the local storage we go local storage again this is built in the browser so we don't need to install anything we go with set item in my case i'll call it favorites and remember that we can only uh save strings so therefore we need to go json stringify and then updated favorites so this array over here and then once we want to remove again basically we'll overwrite so we'll go with local storage set items favorites and then we'll overwrite the existing value with the new updated favorites and then once the application loads we want to grab it from the local storage now there's various ways how we can set up the functionality that grabs the items from the local storage but in my case i went the long way since that way um in my opinion it's more straightforward now can you make this code shorter absolutely but initially i wanted to make it uh easy to follow so here we're looking for the favorites we try to grab the favorites from the local storage we go with get item now there are two possibilities if the favorites exist then this is going to be true and then we just need to parse it because remember we stringify it so now we need to parse it and again we go with local storage get item favorites so we parse it back into array and that is if it exists if not if this is false then we'll set it equal to an empty array we return the favorites and then we invoke this where we have used it again i'm fully aware that there are shorter ways how to write this logic but at least when i'm setting up the content i always want to start with more readable code i think that is more important than having less lines of code and i guess i'm going to go to the context first let's just add the functionality where we want to go with that set local storage or sorry local storage and then we're going to go to set item we're looking for favorites at least that's how i'm going to call it and we need to use json then stringify and we want to pass in the updated favorites now once that is in place we want to copy and paste then essentially we're doing the same thing when we remove the item and here it's actually a bug because there's a missing letter and then let's scroll up and let's set up that function so we want to go with that get favorites from local storage and i'm going to set it up above the app provider we're going to go const get favorites from local local storage it's going to be a function and right from the get go it's going to return the favorites something we're going to set up right here we'll go with let and favorites now that is equal to a local storage get item and now of course we're looking for that favorites all right favorite if it exists awesome we'll have one logic if it doesn't then of course we'll just return an empty array so say favorites is equal to an empty array effectively the functionality we already have but if it does exist then it's going to be different we're going to go with favorites then json parse so we need to parse it again we are saving it as a string so we need to parse it and then local storage and essentially we just want to get this code over here let's just set it up and the last thing we need to do is just invoke it so where we have the favorites let's go with get favorites from local storage let's invoke it so now let's take a look at the application essentially once we add the item to the favorites it's displayed and also it stays there even once we refresh the application with this in place we're done with application hopefully everyone enjoyed it and i'll see you in the next one i hope that project helped you gain a deeper understanding on how everything fits together and react in this next section you'll use what you've been learning and also learn about new react features sanjeev is your instructor for this next section hey everyone for this next project we're going to be building out a stock trading app where users can keep track of their favorite stocks they could see what is the current price as well as historical prices as well now for this application on the main page you're going to see a list of all of the stocks the user has decided to watch and it's going to list out the last price or the most recent price as well as what was the change the change percentage the high low open and the previous close so just some relevant information about that specific stock and how it's doing in addition to that a user can go to the input field up here and search for companies to add to their watch list so if the user wants to search for tesla they can just search for tesla and this is going to send a request to our api and it's going to result in a list of companies that match that specific query we can then pick the specific company that we're interested in and it's going to add it to the watch list so now we can keep track of tesla and if we want to we can remove any one of these so if we want to remove microsoft we can do that as well and the nice part about this is this watch list here is going to be remembered because we're going to store this information in the local storage so if the user navigates away from this page and then comes back to it it's going to remember all of the companies the user is interested in now when we select on one of these stocks it's going to take us to the detailed page for that stock so it's going to render out a nice chart that's going to show historical data not just the current price so right now you can see that it's selected the past 24 hours if we want to we can also see the past seven days and then if we want we can also see the past year and the nice part is it's going to color code it depending on if the stock improved or if it went down and then beneath that it's also going to include some relevant information about the company so things like what exchanges are part of when was the ipo date what's the website for that company how many shares outstanding as well as market cap and a few other details now for the technologies in this project we're gonna be working with a lot of different technologies we've got all of the core hooks like use state use effect but in addition to that we're also going to be making use of the context api so that we can pass data down to the various different components in our application we'll get a chance to work with local storage and in addition to that we'll also be making use of the finhub api so that we can get data about these stocks and for the charting library we're going to be making use of apex charts so in the detail page when we draw out that historical data we're going to be making use of this library and you'll see that this library is actually very easy and intuitive to use and so that's what i've got in store for you guys hopefully you guys enjoy this project and i'll see you in the next section while we get started in bootstrapping the project and just a quick note before we proceed any further because we are using a free account on finhub api uh you'll see that we won't have access to certain data points so when you're looking for companies uh and if you're searching for something like microsoft in this case you want to make sure you just see microsoft you don't want to see microsoft.sw or mi these are not supported with the free tier and you'll see that it'll actually break our application just because we don't have the specific error handling checks for when the user doesn't have the privilege to access the information so just make sure you don't select on these and get the the main stock symbol before we get started bootstrapping our application i want to go over how we're going to handle navigating between the different pages in our application and so in our application we have two main pages when the user navigates to the root path and if you aren't familiar with what that means if you take a look at a url we have http colon slash and then we have a domain so this is gonna be whatever domain name you've purchased for your application uh and so if you own google.com then this is gonna be google.com if you're just working in development mode for your react application it's gonna be localhost colon 3000. so that's a domain and then you have a path following that so in this case this is called the root path because it's just forward slash so there's no specific path after that and so when the user navigates to the root path it's going to take him to the main page here where we're going to have a list of all the different stocks that they're tracking and when they select one of these specific stocks it's going to take them to a detailed page and that detailed page is going to reside at this following url so we have the same http colon slash we have the domain name and then the path is going to be detail slash and then the name of the specific stock so if they wanted to see microsoft it would be msft uh inserted in for symbol and so that's how we want the routing working in our application and the way we're going to actually accomplish this is through client-side routing and we're going to make use of a library called react router and react router is actually very simple and the main idea behind react router is you tell it what are the different urls for the different pages that we want so these are going to be the two urls and all it's going to do is it's going to load a specific component for each url so the way we're going to structure this is when the user navigates to the root url we're going to have a react component and this is a regular react component there's no special componentry needed within react router just makes use of regular react components and we're going to have a component called stockoverviewpage.jsx and so when they navigate to the root path it's just going to load up this component and this component is going to have all of the individual components that make up this page so the way we're going to actually break this down is we're going to have a component for the auto completion and then we're going to have a component for the list of the different stocks and then when the user selects one of these specific stocks it's going to route them to this specific url and this url is going to load up a component called stockdetailpage.jsx and so this component is going to contain the graph as well as the detailed information down here and so that's how we're going to handle client-side routing within our application and you'll see when we get started coding this out it's actually going to be very simple so let's create a new application in replit i'm just going to select the plus button right here and we're going to scroll down and we're going to select react javascript and i'm just going to give this the name of react demo so our projects have been bootstrapped i'm just going to hit run so we can just make sure everything's working and we can see our application was successfully loaded so it looks like everything's working i'm just going to do a little cleanup we don't actually need this text here and in addition to that if we go to our app.css we can either delete this or just comment it out we'll be adding our own styles now for this project we're going to make use of bootstrap just for styling only because i don't want to spend too much time uh having you guys copy all of the css properties and things like that i'd rather just add in a couple of bootstrap properties so that we can have a nice finished polished looking product without having to spend too much time on css so if you go to getbootstrap.com and you just scroll down to include via cdn we want to get just the css only we're not going to be making use of the javascript so we can just copy this to clipboard and if we go back to our application and we can just go to our index.html and inside the heading we can just put this under the title you can just paste that in there we'll save that and then just to make sure that everything's working i'm going to re-add in some text or i'm going to add a h2 tag and just make it say hello or something we'll save that and we should see it in there and i'm just going to add some um classes from the bootstrap library so i'll do class name equals and then i'm just going to say empty dash 2 so this should add or i'll do mt-5 this is going to add in some margin to the top and so we can see it moved down so it looks like bootstrap was successfully loaded and after we get this set up the next thing that we have to do is we have to go to the api that we're going to make use of so we're going to be making use of the finhub stock api this is a free api you will have to register but it is completely free and if you just select get free api it's going to take you to a window where you can register and then once you've registered it'll then provide all of your api keys and so the one you want is this top one right here so you just grab this you can copy it and then just store it in some documentation so you can refer to it later now as i mentioned we're going to be making use of a library called react router so the first thing that we're going to do is we're going to install that so we can set up the routing and so if we select the package manager here and under here we want to search for react router and then more specifically we want react router dom and make sure you get the react router dash dom because there is a react router but that's a different package we want this one specifically here so we'll select react router dom and we can see that it's installing react router dom all right so we'll go back to our files and what i want to do is i'm going to create a new folder in our source directory and i'm going to call this pages so this is going to have the two different pages there's going to be the summary page as well as the detailed page and so i'll create our stock detail page dot jsx and then we'll have our stock overview page as well and so react router dom is going to actually route to one of these two uh components and keep in mind these are just plain react components and so i'm just gonna do export const stock detail page and for now this is just going to return a div that just says this is the stock detail page i'm going to do the same thing for my stock overview page so now that we've got our pages defined i'm going to go back to our app.jsx component and i'm going to import all of the things we need to get react router dom working and so there's going to be three things that we need i'm going to say import and we want browser router we also want routes with an s as well as route singular and we want to import this from react router dom and so we've got these three things i'm going to delete this h2 tag and what i want to do is i want to call browser router and within browser router i want to call in routes and then within here i want to call route so route is going to define the rules right and just to jog our memory and what we want is when the user navigates to the root url so that's going to be just a forward slash we want to load this component the stock overview and when the user navigates to slash detail and then the name of the specific stock so the symbol of that stock we want to go to stock detail page so how do we do that under route we have to provide two things the specific route or path that the user navigates to and then the component should load so for the first one we want to go to the root path so we say path equals and then the specific path so it's just the forward slash and that's going to load up the stock overview component so we have to import that in here first of all so i'll do import stock overview page and this is going to come from the pages folder and then we have stock overview page and to load that component we say element equals and then curly braces and then you provide the component that's going to be stock overview and that's all you have to do and so when the user navigates to this specific path all react router dom does is it loads this component onto the screen that's it react router is actually one of the simplest libraries and that's all it's there to do and we have to set up our next route we'll say route and then we'll say path equal so what's the path for this specific route well we want to do slash detail and then you know whatever symbol now i can't hard code a symbol right because if i say you know msft for microsoft then if they try to check any other company's stock it's not going to work it's only going to match on msft so we need a variable here that can be dynamic and it can be anything the user selects and the way we use variables in react.org is you just do colon and then the name of the variable so i'm going to use symbol but you can call it whatever you want if you want to call it stock you can do that but i'm going to use symbol and it's important to name it something that you can reference because we will need to reference that variable and so when the user navigates to this we want to load a specific element so we'll say element equals and then we just do the same thing and we have to import that component first and then we can just pass that into here and then we'll close off this tag and so now all the routing should be done and if we go back to our components uh we've got everything loaded so let's actually test this out so if i go to the root path which we're already at so the root path is just the forward slash we can see we have stock overview page and what i'm actually going to do is i'm going to open this up in a new tab and this will make it a little bit easier to handle the routing so now if i go to uh if we see the the root path we can see the stock overview component gets loaded and if i go to detail and then just put in some random text it doesn't matter because it's a variable we should see that it should load the stock detail page so our routing is set and everything's good to go and we really won't have to touch too much from the routing side of things because uh we've kind of got all of that said already and so i want to add one quick class so if we go to our app.jsx i just want to wrap this in a container class this is just part of bootstrap everything kind of has to be within a class called container it's going to help with the layouts and once we get that set what i want to do is i want to create a new folder and i'm going to call this component so this is going to contain all of our react components that are not pages themselves so these are just regular react components and if we take a look at the summary page you can see that we have three things we have a logo then we have the autocomplete bar and then we have the table with the list of all of our stocks so the way i'm going to kind of divvy this up is that i'm going to have two total components i'm going to have an autocomplete component and then i'm going to have the table component and so i'm just going to call this autocomplete.jsx and i'm going to call this one stocklist.jsx and so i'll create stock list dot jsx and then the other one is going to be autocomplete dot jsx and i'm just going to copy these components into there just as a baseline and inside our stock overview page i'm going to import both of those components so we can load them onto the screen and then now under this div i can just render out both of those components and we can see that in the stock overview page we've got all three components now or or two components plus the page and so getting started with the stocklist component this is where we get to have a little fun where we can actually finally start working with the finhub api and fetching some data but before we do that we want to store a list of all of the companies or the stocks a user wants to track and we're going to start off by just using the regular use state hook to track that and you'll see that later on in the project we'll actually refactor that and actually make use of the context api so that we can share this data amongst multiple components and so from the react library i'm going to import use state and i'll also go ahead and import use effect because we will have to use that as well and that's going to come from react and i'm going to do use state and then this is going to default to an empty array so uh when you whatever you pass into the use state hook this is going to be the default state so it's going to be an empty list of stocks and then i'll say this equals and then we'll say const and then we'll we'll call this a watch list so it's going to be a list of all the stocks that the user wants to the user wants to watch and then the function that we're going to get to modify this list will be called set watch list okay and so this variable called watchlist is going to return all of the stocks they want to watch and if we ever want to update it we make use of this function and actually instead of defaulting it to an empty array just for development purposes i'm going to hard code a couple of different stocks so that we don't have to manually go in add in a couple and then and then be able to fetch the data that would just require too much work so we'll add in a couple stocks at first as a default and then we'll clear this out once we're done with our project and for now i'll just say maybe the user wants the track of google and we'll say microsoft is the other one and then amazon okay so when the user navigates to this application they'll see data for these three stocks by default and i realized i actually made a mistake um when we actually send the requests to the finn hub api it expects everything to be capitalized so i'm going to change this to be gogl and msft and amzn yeah that actually got me for a little bit i forgot to capitalize it and i think we should actually go to the documentation so if you go back to the fin hub website and select documentation it's going to open up a new tab and it's going to show us how to actually work with the api and the first thing that we have to understand is that from an authentication perspective we have to provide the token as a parameter so we have to say token equals api key for every single request and that has to go in the url or you can add it as a header whichever one you prefer i'm going to go with the first option and the url that we have to send a request to is going to be this https colon slash finhub dot io slash api v1 so all of requests will go to this base url and then we provide a specific path depending on what data we want to retrieve and if we actually go down to the documentation what we want to do is go under stock price and then get quote this is going to be the first endpoint that we're going to access so once again we take the root url and then we go to slash quote and this is going to give us information about a specific stock and it specifically gives us what's the current price what's the change percent change what's the high the low what was the open price as well as the previous close so it's going to give you everything we need for our table and all we have to do is just go to the slash quote endpoint and then we have to do a question mark and then here this is going to be the uh query parameter so everything you see after the question mark is going to be a query parameter so this is kind of providing the api uh specific data that we're looking for so we say symbol equals and then the name of the stock that we want data for and then we want to provide another query parameter and you separate the two with the and sign and then you have to provide the token so for every request we're going to have to add the token and then for the specific quote endpoint we have to provide the symbol so we can just send this as an example and then just update our token and that's going to be the request that we need to send in you can see that the documentation actually pre-fills it with my token so you could just copy this directly from your from your computer and it should work as well so let's work on getting this set up now we can fetch data using the fetch api that comes built in or we can make use of a library like axios and um i prefer to use axios there's no issue with using the standard fetch api but it does make it a little bit easier to work with you know path parameters and query parameters as well so i'm going to install axios and i've actually already got it installed but you can just search for axios and select the first one so this is the one that we want and you can see it's already installed for me so i've already done this so go ahead and do the same thing or if you want you could just do it through the standard method of just doing npm install axios whichever one you prefer now once we got axios installed what i'm going to do is i'm going to create a new folder called apis and this is going to contain all of the files for our api and within this api folder we're going to set up for one for the finnhub api i'm going to call this finhub.js and here we're going to set up axios and so i'm going to import axios from axios and then we're going to do export default because i'm going to export this instance of axios i'm going to say axios dot create so this create method creates a axios instance and here we provide some configuration options and the first one is going to be base url so you do base and you can see it's going to auto complete and you want to make sure that the ur and l are capitalized and here this is going to be the base url for the finn hub api so if we go back to the documentation the base url is going to be from v1 all the way to https so we'll copy that and paste it in here and make sure you don't have the forward slash at the end you want to delete that we just want it to end at v1 so by default when we use axios now or the spinhub.js api it's always going to set this as the base url and then we can add in whatever specific endpoint we want so if we want that slash quote endpoint we could basically just do a plus slash quote and then uh axios will combine them together so that you don't have to retype this entire url out and for now this is going to be all that we need uh we'll make a few changes for uh to this a little bit later but we can go back to our components and go to our stock list component uh we can then oops it looks like i accidentally deleted my use effect hook so now we're going to use a use effect hook so that we can fetch data and i'm going to import my axios so i'll do import binhub from dot dot slash so we're gonna go up a folder api slash and then binhub and so now we'll call the use effect hook and we'll pass in a function and right here we want to specify the dependency array and the dependency array is going to determine when this hook runs if i don't pass a dependency array what's going to happen is this hook is going to run every single time the component renders which would mean we would be fetching data every time it renders and that's not what we want we only want to fetch data when the component mounts so the component mounts we fetch the data that's all and to make it so that it only runs when the component mounts you pass in an empty array and that's it and i'm going to define a function in here called fetch data and this is going to contain all of the logic for fetching that specific quote and i'm going to wrap everything in a try catch block in case we get any errors and in here we can then do finhub dot get and for the url it's just going to be slash quote right because if we go back to the documentation right we just want to do quote and since we already specified the base url it's our it's automatically going to add that and then we want to specify the symbol and then our token of course so i'll say question mark symbol equals and then just we can grab microsoft and then we'll do and and then we'll do token equals and then we'll copy our token and paste it in here and then we will save this to a variable and i'll just call this response and remember this is a asynchronous action so we want to await it and because we're making use of a weight here this function has to be an async function and then down right below that i'm just gonna do a console.log response and then we'll actually call this fetchdata function so that we can actually fetch the data and it looks like there's a typo this has to be a capital h all right and it looks like it did fetch something so let's take a look at the data and if we take a look at the object this is uh what axios return so it shows us the original config which is under config the data is actually going to be the response we get back from the api so that's usually what we're most concerned with and if we go under data you can see we did the closing price the change price the high low so it looks like we were successfully able to get this data and moving forward um we'll i'll probably just show you everything we get back from the api in the console in a separate window just because it allows me to make it a little bit bigger and easier for you guys to read so we can see that the data was shown up here as well all right so that's great uh now we were able to fetch this data however i don't want to have to copy and paste the token into every single request because this isn't going to be the only component that has to get data from the api and i don't want to have to copy this token around all over the place so what we can do is first of all uh what i would prefer to do is go under our apis and here for our axios instance we can already pre-bake our token so i'm going to create a variable i'm going to call this token or key whatever you want to call it i'll call this token and i'm going to paste my token in there and what i can do is i can add in another property called params and then here i'll say token is going to be set to token okay and so now when we send requests i don't actually have to include this token parameter because it's going to come built in with the finhub axios instance and so we could see that it was actually able to get the data again and on top of that the great part about axios is that i can more dynamically add these query parameters without hard coding it into the url by removing this and i can actually just add in an object so i can pass in an object here and i can say params and then i can provide the symbol which is going to be set to microsoft yep and looks like it worked so now once again we got the data from the api server so this is just a different way of configuring axios and i think it's a little bit cleaner and easier because now we don't have to provide the token on every single request and now our request is pretty simple we just have to provide the symbol okay so now that we can fetch data from the api let's save this in some state variable so i'm going to call the use effect hook the use state hook again i'm just going to leave this empty and we're going to store this in a variable and i'll just call this stock so this is going to contain all of our stock data and then we want set stock so we want to manipulate that and so after this console.log i can just do a set stock and then we want to set it to response dot data and the reason why i said response.data is if you take a look at the response remember the response is going to contain the config which is the axios config is going to contain the headers request we just want the data so that's why i said response.data now one thing to keep in mind when fetching data with the use effect hook is there's a possibility that you know after we sent this response out that our component actually got unmounted and so what we don't want to do is end up calling set stock on a component that's already unmounted so how do we prevent that well it's actually very simple what i'm going to do is i'm going to define a variable and i'll say let and i'll just say is mounted this is going to be a boolean and i'm going to say this is set to true so what happens is when the component mounts right this is going to run when it mounts it's going to set mounted to true and then before we do set stock we just do a little check and i say if is mounted is set to true then we can move this up into that if statement that's all and all we have to do is then when the component unmounts we call a return to the use effect hook so this is uh this function that we pass to return is going to run whenever the uh the component gets unmounted so i can say when the component gets unmounted i would just want to set is mounted equals false and so that way when we get a response back and the component got unmounted this check will run and it will not pass and it'll just skip right over it because we don't want to accidentally call set stock on an unmounted component now the next thing that we want to do is now that we're able to fetch some data we want to fetch data for everything in our watch list right now we have three different items and there's a couple of ways of going about doing this the first thing that we can do is i can just take this and just copy it three times and then i can just change the symbol to be the specific uh stock names so we'll have google microsoft and then amazon and i could maybe create a array i'll just say const responses equals empty array and i'll just put a number after these and then we can say responses dot push now do response one and we can just copy this three times and just change this to be response two and then response three and then for set stock instead of sending response that data we could just send the array responses and so let's test that out okay so after i fix that little typo we can see that it printed out all of the responses and i've got the responses for uh this is going to be google the next one is going to be for microsoft and the last is going to be for amazon so we were able to get all three of these however there's a couple things i don't like about this right let's ignore the fact that i'm hard coding all of the different companies because this is going to be a dynamic list that should be changed by the user but what i don't like about this is this is happening sequentially so what happens is we send a request to get the information for google and then once we get the only once we get the information back from google we'll then move on to response 2 and get the data from microsoft once we get the data from microsoft we'll then go and get the data all right this is very slow because we're doing one at a time we're sending one request to the api server and in fact if you go to the chrome developer tools and you go to network and so if you take a look at how long these requests take we can see the first request where we send the request to get google it takes all of this time only once we get the response back can we then go to the second request and then only once we get the response back can we go to the third request so it's doing these things one at a time and that causes this to be a very slow process and if the user wants to see um you know the data for 20 stocks imagine sending each one of those one at a time in series i would prefer to be able to send all of these requests all at once and then the api server just responds them as they come in and that way it should basically take the time it takes to send one request because we're sending all of them concurrently so how do we do that in javascript well what i'm going to do is i'm going to delete all of these or actually instead i'm going to leave those and i'm going to show you guys a tool called promise dot all when you call promise.all you provide a list you provide a list of promises and it's going to try to resolve all of them at once so it's going to send a request for all three of these guys all at once and so i could just copy this config starting from finhub and paste it into here and then just do a comma and then the second one and then finally we'll grab the last response so now i can delete all of these and all we have is this promise.all which has three different promises getting sent to one for google one for microsoft one for amazon and i can delete these and i'll set this to be const promises equals promise that all or actually let me just change this to be responses so we don't have to change anything else and now if i refresh this and it looks like it hit the api limit so i'm going to give it a couple seconds because we have at most 60 requests uh per minute so i'll give it a minute or two and then we'll run the request again and we'll take a look at um how quickly it works now okay so um because of the way react works uh it actually runs that use effect hook twice it basically mounts the component twice so ignore everything from here down what we care about is the first three and notice the the timing of the three requests they all get fired off at the same time and they all roughly complete around the same time so look how much quicker that is versus sending one and then only after that's done we send the next one and then only when that's done we then send so this goes all at once and it basically takes the time of one request because we're sending it all concurrently and so that's all done because of this promises promise.all method so that's great however we're still hard coding all of the companies we don't want to hard code the companies we want to take whatever's in the watch list and then create these dynamically so how exactly do we do that well it's actually pretty easy what we're going to do is we're going to make use of the javascript map method and what our main goal is right we have a list of companies and for each one of these we want to take this string and we want to generate a promise so we want to send a request using this axios instance and we want to do this for each one of these three and so anytime you want to make a change to every item of an array uh you want to make use of the map method i want to show you how that works so here i have this uh this uh array right here with the the three stocks like we had before and let's say that after each stock i just want to add an exclamation so i want to end up with an array where each stock has an exclamation how do i do that well it's pretty easy using the map method i'll say all we have to do is i'll say map i'll say well we call stocks and then we call the map method and what this is going to do is this is going to iterate through every item in the array and so we have to pass a function to tell it what do we want to do and this function gets one argument uh the well actually it gets multiple arguments but we're going to focus on just one which is the element and then we have whatever we want the function to do so what is the element well as we iterate through this array the element is going to be whatever the current item is that we're iterating over so the first time this runs it's going to be an element is going to be set to google the second time this runs the element can be called microsoft and then the third time it runs it's going to be amazon in fact if you want to make this a better name we can call this stock so this represents one of the stocks and then what this function returns is going to be what you want to change it to so we have stock which is going to be set to whichever one we're iterating over so the first time it's going to be equal to google so i'm just going to put this in the comments so this is going to be equal to google or google and what we want to do is we want to add an exclamation rate we want an exclamation like that so all we have to do is just return what do we want to change it to so we want stock plus exclamation that's it or you could do string interpolation and say um stock and then exclamation and so when it iterates through google it'll add the exclamation then when it iterates through microsoft it'll add the exclamation and then when it goes through amazon it'll add the exclamation and then we could set this to a value so i'll say this is my modified stocks because the thing about the map method is that it returns a brand new array and if i do a console.log modified stocks save this and then do a node test.js all right you could take a look at the result it successfully added the exclamation afterwards so we get access to each item as it iterates through it and then whatever we return in the function is going to be entered into the new array and so we're going to do the same exact thing with this but instead of adding an exclamation point we're going to generate a promise or a request to our api by calling the same thing so i'm going to delete all of this instead we could just call our watchlist array i'll say watchlist dot map okay and once again we're going to pass in a function we get access to the stock or the element that we're iterating over and then whatever we return from this function should be a request to our api so i'll say return i will do finhub dot get slash quote and then params and remember we want symbol and we'll set that to be stock because stock represents the symbol that we're currently iterating over and we just pass that in there so now if we test this out and i realized i forgot to do an await now if we take a look at responses we should see that we have now successfully gotten all three of our requests and if we go to our network section we can see that all three of them gets uh got sent out at the same time so that's exactly what we want and so i think we've pretty much done everything we needed to do there if you want to you can set the use state uh hook to be uh by default just an empty array it doesn't really matter however um before we kind of wrap things up and move on to rendering out all of this information uh inside a table if we actually do take a look at this console.log right here which is uh printing out all of the response objects before we uh store it into our state there's something i don't like about this and if we go to our console and we take a look at what the output looks like this is what's getting stored in our component state and if i open up the first one take a look this isn't actually just the data that we get from the api this is the response object from axios so we get the configuration we get the data which definitely what we want we get the headers and the request and most of this information we don't care about why would the component care about the configs of our axios request it doesn't why would it care about the headers it doesn't what about the request it does it the only thing our component cares about is the data i don't want anything else other than just the data so for each of these three items of these three requests i want to go in and extract the data and just delete everything else because we don't want to store unnecessary information in our state so ultimately what i want to do is and i'm just going to create a new file here this is just for demonstration purposes you don't actually have to do this yourself i'm just going to call this demo.js what i ultimately want to do is i want to store in our state for each one of the stocks an object that looks like this so we have the data which is going to contain all of our you know stock data whatever it's called and that's going to come from the data object here and then the next thing i want to do is notice how inside the data it says nothing about what stock this data is for so that's something we have to assign ourselves we can't just extract it from here in fact the information about where the stock is is actually within the config so if we go to the config under params we can see the symbol so inside here we want data to come from data and then we want to whoop data to come from data i'm just going to put this in quotations because the autocomplete's messing it up and then for the symbol this is going to come from config.params.symbol so i want to store this information an object that looks like this so before we save it into our set state i'm going to call the map method to iterate over all of these things and extract an object that looks exactly like this so we are already familiar with the map method so we could just do that again and i'm going to delete this demo.js and we'll go to our stock list and right here before we call set stock i'm going to do a responses dot map and we'll just say this is going to be response and like i said what do we want well we first want to get the data which is going to come from response.data right that's going to be data so the response which is you know in this case the first response we want the data property which is going to return this uh object here and then i want to store information on what is the symbol and that's going to come from the response and i already forgot where it's coming from but i believe it's config params symbol so config params symbol and remember we want to return an object so right now i didn't actually put it in an object so let me create that object and then paste that in here and then we return that object and we'll store it inside a variable called data and then change the set stock to be data and we'll save that we'll go back to here and i'm actually going to print out what our data looks like just to make sure everything looks good and so now we can see that data has just the data that we're looking for and then symbol is set to google so that's exactly what we want now our state looks exactly the way it should so now what we can do is work on rendering out this information inside a table so inside our table for the headers we want one for the name of the stock we're going to have one for the last the change the change percentage the high low open and peak so this is all going to go inside a table element so in our return statement i'm going to remove stock list inside here we'll do a table and i'm going to add a couple classes that come from bootstrap is going to be table hover and then mt-5 so this is just the usual styling for the table this uh we'll make it so that when we hover our over one of the stocks it's going to change the color so we know which one we're hovering over and then this is just going to add a little margin to the top then we want to create our t head right so this is going to contain all of those headers that we just went over and i'm going to add some inline styles which is nothing more than just changing the color and now we'll do tr we'll do th scope equals this is going to be the name and i'm just going to copy this several times all right so now if we take a look we can see we've got our table with the different headers now we can add the actual data and the way we're going to render out this data because remember all of our data right now is stored inside this uh stock state uh is once again we're going to use our favorite map method so i'm going to call uh i'm going to do a curly braces so that we can provide some javascript and we're going to map through this so we'll do stock.map stock data and we want to return and so for the the row it's going to be th and here we're going to provide the stock data dot symbol and for the tr i'm actually going to add in a class this is going to be table dash row and remember because this is react we have to provide a key for each element we return in a list i'll say key equals and this is going to be stock data dot symbol we'll use the symbol as the key and so for this right then we can do td uh the next one's going to be stock data whoops we want stock data dot data dot c next one is going to be stock stockdata.data.d i'm actually just going to copy this a few times next one's going to be dot dp and then we have h l oh and then pc and it looks like i made a little typo here this shouldn't be dot symbol in the curly braces all right and now if we go back to our website when i clear this let's refresh this just make sure there's no errors we could see that we now have our chart and it's automatically going to get updated depending on what is our stock state a couple of final things that i want to do from an aesthetic purpose for our stock list component is that first of all we should color code the change and change percentage value depending on if it um if the stock went up or if the stock went down so we're just basically checking is the change negative okay we want to make it red if it's positive we want to make it green in addition to that um we also want to add in an icon showing the direction uh that it moved so if the stock went down we want the down icon if it went up we want the up icon so those should kind of go hand in hand with the change value so just to kind of hard code something if we go to the this td right here this is for the change and the change percentage if we want to change the color using bootstrap we can do class name equals and then text dash success that'll give us a green color and then if we change the bottom one to be class name equals text dash danger that's going to be the red color so now you can see under the change where we have text success we can see it's green and then when we see text danger it's going to be red so we have to define a function that'll check the value of what direction the stock went and then update this specific class depending on if it was positive or negative and so what i'm going to do is i'm actually going to delete success and danger so for these two we're just going to have it say text dash text dash and then what i want react to do is call a function that's going to contain the logic for determining uh if the stock went up or down and so first of all we're going to provide some javascript and we're going to use template literals and here i'm going to pass in a function that i haven't defined yet called change color and what we should do is we should pass in the stock data.data.d so that's going to determine the direction that the stock went and i'm going to define this function now it's going to be called change color i'm just going to define it right above our use effect hook so it's going to be const change color and then it's going to get in some variable and i'll just call this change and we're just going to use the ternary operator to do a return and we'll say if the change was positive so that means the stock went up we're going to return the text success and if it was not positive so that means it's negative we're going to return danger okay and so now we can see that it's automatically updating the color everything was negative in this case but if we have a positive stock then that should automatically turn green i think our entire stock market's going down so everything's just red at this point we're gonna do the same exact thing for this guy right here i could just copy this and just paste it in and we've got these updating dynamically as well next thing that we have to do is add the icons and i'm going to make use of a library and so we'll go to the package here and and we'll install a package called react dash icons and this is the one we want right here so i'll add this so for this library if we take a look at the documentation we can see that it supports icons from several different um you know frameworks uh we since we're using bootstrap we might as well just stick to bootstrap icons and the way that it works is that all you have to do is you do import the icon name and then you do react dash icon bs for bootstrap and all we have to do is then find our specific icons so it's going to be this one right here bs fill carrot downfill and if i search for carrot we should also be able to find the up one so bs fill carrot upfill as well and so if you just select this it's going to copy it into our clipboard which is awesome and now if we go to the top of our file i'm going to do import paste that in from react dash icons slash bs and this is just a regular component now so i can go down here and after this i can just put in another component all right and now you can see that you can see that the component is right there next to it so that's all we have to do however we have to select the right icon depending on what direction it's going and so what we're going to do is we're going to set up another function just like this change color function i'm going to create a render icon function that's going to do essentially the same thing so here i'm going to delete this and in here we'll pass in our function render icon and we'll pass in the same information which is going to be stock data dot data dot d and then i'm going to define our function const render icon get access to the change again and we're gonna do the same thing change greater than zero we're going to return and actually have to import the other one as well so we want the up carrot up fill and if it goes down then we're going to return the other one and i can copy this and paste it into this one as well now if we take a look we could see that all of them have an icon so i think that's a good stopping point on the stock list component there's still a couple more features we're going to have to add to it but i want to take a break from it for now and i want to move on to the autocomplete component and just to remind you guys what this component does it's going to be a simple input field where the user can search for available stocks so if the user wants to find you know tesla you'll just start typing in the letters tsla and you'll see that it should be able to search through that and it's an autocomplete so if you actually go slow enough and i just type in ts it's going to find all of the companies that start with ts and then i can just keep adding another letter and then it's going to keep narrowing down the field until we get to what we're looking for and then from there we can then select the company and then it's going to get added to the list and i want you to take a look at the network request right the for each letter they type it's going to automatically send a request back to the api so for the headers you can see that uh in this case the query it just has the letter t and the next one has the s l a so we send a request for every letter and you know we can obviously customize this so we don't send it for every single letter the user types however i wanted to keep this component as simple as possible so let's tackle creating this component and so we'll go to our autocomplete.jsx and within here in this parent div i'm going to add in a couple of class names uh it's going to be the width is going to be set to 50 i'm going to add some padding i'm going to give make it rounded and then the margin is going to be auto so it centers and within this div we'll now add our input actually before we add our input i'm going to add another div i'm going to give it a couple classes so it's going to be form dash floating and then drop-down and within this div we'll then add our input and for the input we're going to add some inline styles mainly just the background color i'm going to give this an id of search type is going to be text and i give this a class name of form control this is coming from the bootstrap library and i'll also give it a placeholder of search and if we just take a peek at what this looks like that's pretty much what i want it to look like and for my autocomplete i'm going to disable the built-in autocomplete and then under the input i'm going to add a label we'll do html4 this is going to point to search so this is going to match up with the id of this input field and the label is going to say search all right and just to double check let's just take a look all right everything looks good now the next thing is we want the drop down so how do we make the drop down well there's all this is going to be pretty easy with the bootstrap library for the drop down under the label we can create a ul so i mean we can really render anything in the drop down and then i'm just going to add a couple of items i'll just say stock one two and three and for this ul we're gonna add in some class names mainly drop down dash menu and that's all we really have to do so this is our drop down and i'm going to actually go back to my browser for a second okay so you'll see that right now there's no drop down however if i inspect this and go to elements we can inspect this and then go down you can see that the drop down is there it's just right now at the moment if we go to computed we can see that the display is going to be set to none right now the drop down menu is set to display none so you don't see it so it's still actually on there but it's just being hidden and that's because when you assign drop down dash menu from the bootstrap library it's automatically going to give it a display of none and if you want to show it using the bootstrap library we have to add in a class called show and so now the drop down actually shows so this simple class is what is what's going to determine if we show the drop down or not so this is something to keep in mind and make sure you keep that on the top of your head when we're implementing the logic of you know rendering out all of the data once we start searching for it the next thing that we have to do is we have to make this a controlled input and this is going to be like with any other standard input in react so i'm going to import the ustade hook and to make this work i'm going to create a variable called search and set search so this is going to represent whatever the user is trying to search and i'll do use date and default is going to be an empty state and then in my input field we're going to set the value of the input to be set to search and then we're going to set a on change parameter whenever the user types in something and i'm going to say we're going to pass in a function and we're going to say that set search set that to be the value of e.target.value okay so what we're doing here is i'm saying that whenever the user types in you know a letter it's going to trigger this on change which is saying uh get the value of that of the letter that we just changed or whatever is our input field and set that to the set search function so that we can update our state and then the value of our input will be synced to whatever our state is so that's how we make this a controlled input and we can see everything types out just fine and if we can actually go back to the browser type here and go to my redux dev tools extension and go to the autocomplete we should see that the state should match up with whatever's typed okay looks like everything's good and now the next thing that we want to do is implement the fetching data logic so i'm going to import the use effect hook and then we're going to call the use effect hook and we'll do the same thing that we did before we'll pass an error function and before we get started sending a request or implementing the logic let's go back to the documentation and take a look at what endpoint we need for searching and the one we want is under stock fundamentals and under symbol lookup so you send a get request that's going to be the method and you send it to the slash search endpoint and you provide one query parameter which is the letter q and then whatever text the user searches for and then this is what one of the results are going to look like so it's going to include the you know the type symbol display symbol and then the description and so that looks simple enough so once again i'll do we'll define a function called fetch data we'll put in our try catch block and then below this we'll call fetch data and let's import our api our finnhub api and now we can do a const response equals and then we'll do binhub.get the endpoint is going to be the search endpoint and then params well this is going to be set to this queue and that will be set to the value of whatever the user searches we just say search and this is an asynchronous operation so we'll do a wait and then i'll do a console.log of response so let's take a look at that and so right away even though we haven't typed anything it looks like it's fired something and if i take a look at the config and get this is going to let's see where's the params yep params right here we could see that we're sending it with a empty search and when it sends an empty search to the api it returns everything so we got an array with 11 000 results so that's obviously not something what that we want and so right there what i think we should do is um we should first run a check and say that only if search dot length is greater than zero so if there's only if there's at least one letter that the user has searched then we call fetch data okay so let's reload this and so these these first results are just from this table um but we can see that we didn't actually uh search anything it didn't actually try to send a request to the search api so let's try um sending one letter and we can see that it did in fact send a request and we could see that the results as a whole bunch of stocks are companies with the letter a in it let's add another letter and this time if we take a look at the config we can see that the search is a n and the data we know we now have 28 results we do the letter e now we should see that we now have 29 results and let's try one more letter and we can see that we have 25 results okay so it looks like it's working um but one thing that is happening with the use effect hook is that right now since there's no dependency array it's going to run every single time every single time the component re-renders and we don't necessarily want that we only want this to run anytime the search changes right because why else would we want this to run it's all we only want to send a request whenever the user has changed the search either added a letter deleted a letter or made some change or pasted something in so what we can do is under the dependency array you just say search so now this use effect hook will only run when search changes the next thing that we have to do is we have to store the results someplace the results from the api so i'm going to use the use state hook again and i'm going to call this a results and down here what we're going to do is i'm going to set results to be results dot data sorry response.data and once again just like the previous component that we worked with with the stock list we also want to do this is mounted trick where we make sure that the component is still mounted and so we also have to perform the return operation where we set that to be false so i'll copy this and we just do a check here is mounted okay so let's uh let me go to my redux or my react dev tools again i'm going to go to my autocomplete component and we're just going to take a look at the state so if i type in the letter a we could see that the state was now set and it looks like the way that the object was set it's a it's returning a count and a result i just want the result i don't want the count in there as well so i'm going to do response.data dot result let's try this again a okay we've got the results that's exactly what i want let's see if it updates right now there's 42 now there's 24 perfect now let me change that to an a we get 42 again and then if i set it back down to zero what do you think is going to happen so after i search something notice how the state doesn't get cleared out the state still has that a search result so what's happening here well if we go back to our code you can see here if it says that if search dot length is greater than zero we'll fetch data and in fetch data we set the results however what happens if we have a length of zero a length of one and then go back down to zero so we delete a letter well at no point are we updating set results to be back to an empty array so what we have to do is just put an else statement here and just say set results to an empty array and so that way if i type in the letter a i'll get 42 results again and then when i delete it it's going to hit that else statement and then it's going to remove all the entries and i'm going to delete the unnecessary console.logs okay so we've got all the data fetching logic implemented now we have to just show the drop down and so how do we do that remember i talked about how all we have to do to show the drop down is add this class called show and then it's going to show this drop down so what i want to do is uh implement a function that's going to figure out if if search has or if results is not empty then i want to add the show class if results is empty then i don't want to show it so i'm going to define a function called um render drop down so this function is actually going to be responsible for rendering this ul so i'm actually going to uh comment this out for now that didn't work and i'm going to put in a little logic i'm going to say drop down class equals and then we check if search is a true value so if search has um you know any text in it then it's going to return true if search is an empty string then it's going to return false so if it's true and there's some search in there then we're going to return the class show because that's what shows the drop down if not we're going to return null and then the rest of this class is going to be responsible for returning that ul so it's going to render out that ul and for class name what i can do is add a little trickery and i can say drop down dash menu and then i pass in drop down class so it's going to add in show if we have some sort of search result and for now i'm going to hard code some lis again okay so i type in a letter and i realized we have to actually go down here and call that function render render drop down so if i type in a you can see that now since there's a search result it renders out the drop down if i delete it it goes away so that seems to be working now all that we have to do is we have to take the results that we have and render out that information so we'll go to our render drop down we'll just delete these lis and once again we're gonna do our favorite map method so i will say results.map we have our li let me add in a class name of drop down dash item and then what i want is we have two values there's going to be result.description and then result dot symbol so i want the company name and then followed by the result uh of the symbol of the company and i actually want that wrapped in parentheses so i'll do parentheses let's try this again all right look at that so i got the company name followed by the ticker and we can see this is a massive list and what i want to do is i want to implement some scrolling and i want to hard code the height of this uh of this drop down so it's not going all the way down like that i don't like the way that looks and to change that under the ul we're going to add in some inline styles the first thing is going to be the height i'm going to set this to be 500 pixels overflow y so this is going to set this to be scroll uh overflow x i want to i want to hide the scroll bar in the x direction and i also want to add change the cursor to be a pointer so the user is aware that he can select one of them let's try this again that looks much better you can see we can scroll through the results and one other thing is that since we're rendering out a list of items just like with any other list in react we have to provide a key so i'm going to set the key to be the symbol again so we'll say result dot symbol so now that we've set up the autocomplete functionality the next thing that we want to do is after a user searches for a list of companies once they find the company that they want to add to their list they should be able to select it and then it should show up on this list so we should set up a on click event handler so that when they click on a specific li it should then add it to the list of stocks that the user watches now the problem with this is that the list of stocks that a user wants to watch is currently in the stock list component under the watch list state so our autocomplete component does not have access to the state of the stock list component so we're in a little bit of a pickle and i've set up a powerpoint just to kind of quickly show what the issue is and how we can tackle the the issue and some of the different solutions that we have at hand in the stock summary page we have basically three components we have the stock summary page component itself which is responsible for rendering out the stock list component and the autocomplete component and the stock list component has the list of stocks the user wants to watch that he's storing in a use state hook and the variable's called watchlist and the problem with this is that unfortunately the autocomplete component does not have access to the watch list so when the autocomplete component wants to add something to the watch list at the moment he cannot do that so we have a couple of different options the simplest solution to this is to lift the state of this watchless state up a component specifically up to the stock summary page that is a parent component to both of these components and then what we can do is then we can pass that information down um as props to stockless and autocomplete and that would work just fine however what i want to do is i want to make use of the context api i think this is good for learning purposes and you can take a look at how we can create global state using the context api and the way that the context api works is actually very simple what's going to happen is we're going to create a component called a provider component and this is really fundamentally just a regular react component that wraps your entire application and so by wrapping your entire application in this provider component what it does is it allows individual components to access its state so we can move the watchlist state up to the provider component and then the stock list and the autocomplete components can then query the state and get access to that state directly and any other components in our application can access it directly without having to pass it down as props so that's what we're gonna do moving forward we're gonna implement a a context to store our watch list and give us functions uh that'll manipulate being able to add and remove items from our watch list so let's go ahead and implement our context i'm going to create a new folder in our source directory called context this is going to store all of our context we just have one for this project i'm going to call this watchlist context dot jsx and to create a context we're going to import create context from the react library so i'll do import create context from react and then to actually create the context all we have to do is export cons i'm exporting it because we're going to have to import it in another file and then just provide the name of your context so i'm going to call this watch list context and then we call create context and we have now successfully created a context after we create the context what we have to do is we now have to create that special provider component to wrap our application in that provider's component that provider component is responsible for passing data down to any components that's interested in receiving that data and to create this component it's just a regular react component almost 100 identical we just do export const and then i'm going to call this watchlist context provider you can call this component anything you want but i usually just like to grab the name of the context and then add the word provider afterwards and then we'll pass in the props and then we have to return and this is the only difference so we're going to return a special component called watch list context so we're grabbing the context right and from there we can grab something called a provider component and that's all you got to do and this needs the dot provider as well okay and so what we can do now is we can take this provider component and wrap our entire application and our application can have access to any data they want and when i say any data at once it means what i mean is any data within this component because like i said this component is just a regular react component that can make use of the use date hook the use effect hook any other hooks that you want and so the stock list has access to the watch list and i want to make this watch list accessible to all components what i'm going to do is i'm actually just going to take this from here remove it from here and i'm going to move this exact use state hook into my context because remember my provider component is just a regular react component so i can just paste that in there and i can now manage my watch list within my provider so how do i actually pass this data down to my other components well inside this component here i have a value prop and here i can pass down whatever i want so if i want to pass down watch list i can and this is perfectly fine but i'm going to in the future pass down a few other pieces of information so the data that i want to pass down in the value prop i actually want it to be an object and this is just an example of what i want it to look like it should be an object obviously watchlist should get passed down and i will also have an extra function to add a stock to the list to the watch list as well as delete a stock from the watch list as well so that's what i wanted to look like so what i'm going to do is i'm going to remove this instead of just passing watch list i'm going to pass down an object because i want an object and right now i just have a watch list but we'll implement the logic for those other things in a second and i'll remove this so our context and our provider component are done we now have to take our provider component and wrap our entire application so if we go to myapp.jsx and it looks like it already got imported but i'll just type that in real quick for you so it's going to be import watch list context provider we want the provider not the context from context watch list context and now we have to take this special component and wrap our entire application so technically you don't actually have to wrap your entire application you just wrap it in whatever subset of components should have access to that provider so i'm just going to wrap my entire application just to keep it simple and i'm going to call my watch list context provider and i take the bottom one and then just move it under browser router so now if you actually take a look at our application our actual application is this and all of these components within this watchlist context provider have access to that value prop that we're passing down and i'm it's it's throwing an error and that's just because i'm using this use state hook but i never imported it so we'll import it okay so everything's done no errors but interestingly enough nothing is being rendered onto our screen what's happening well we know that we changed the watchlist context provider and we added in here so that's obviously breaking it but let's understand why it's breaking so notice how our application starting from browser router is now being passed into our watchlist context provider as a child prop right it's no different than you know if i had like a an h2 and then i'm providing you know some text right some text is a child prop i'm passing it in between the tags so if i go to my context provider take a look at what we're rendering we get the props but we're not doing anything with it right we just have our context provider and that's it so we have to tell our context provider hey let's render all of our child props normally like they should be so all we do is just do props dot children so this is going to render all of the context between our provider tags okay and now if you take a look everything is working as it should if we take a look at our app it's working and more importantly if i go to my watchlist context provider in my react dev tools we can see that our state is being there and is working and we can see that everything looks to be good and now our next task is going to be how can we make it so our components have access to the state within our provider okay so now to make it so our stock list component actually grabs the watch list from our um from our context instead of storing this himself we're gonna actually remove this i'm gonna delete this it's gonna break our application that's okay and to retrieve the data being passed down in this value prop what we have to do is we have to make use of a specific hook called use context so i'm going to import use context and then we just say use context and then we have to pass in the a reference to the actual context which is watchlist context so we have to import that as well i'll say import watch list context remember this is the context not the provider okay and then we store this in a variable you know const value but that's going to return this entire value prop if you want we can just do a console.log a value and if we take a look you can see that we get access to an object with the watch list so that's perfect that's all we have to do to get access to anything passed down from a provider now we don't need access to the entire value we just want access to watch list at the moment so i'm going to destructure out watch list and now our app is going to work exactly as it should and i need to remove that console.log all right perfect so now we can actually go back into the autocomplete component and implement the logic for adding a new stock but what i want to do is i don't want to store that logic within the autocomplete component i want to store that in my context and i want the context to pass down a function so that the only thing the autocomplete component has to know what to do is just call that function so let's go back to our context and i'm going to define a couple of functions so the first one is going to be add stock how do we add a stock to our watch list so this is going to be function and this function the autocomplete component is going to pass the name or the symbol of the stock and all we have to do is say if or and all we have to do is just say set watch list and then we spread the current so we copy over the current watch list and then we add in the new one and the new stock and that's it however this is going to create one issue and that is that what happens if we try to add a stock that's already in this list right let's see google's already in there and then the user searches google and then tries to add it well now we're going to end up with two googles and that would look stupid in our application we don't want to have the same stock listed twice so we have to perform a check to make sure that the stock that's passed into this function doesn't already exist in the watch list easiest way to do that we could just do an if statement and just say watch list and then we call the index of and then we pass in the stock and if this equals equals equals negative one that means it's not currently in that list so only if it's not in the list will we add it in and so that's all the logic for adding a stock let's now implement the logic for deleting a stock and to delete a specific stock from a list we can call watchlist dot filter and this is going to iterate over the array and we'll get access to the specific element it's iterating over and we'll just say we want to return if element does not equal equal stock so that means it's going to go through the list in our current watch list and it's going to find all of the entries that do not match the stock that's passed into this function and if they do not match then we will keep it but if they do match we'll delete it that's all and then this is going to return a new array and so all we have to do is just then call set watchlist and then pass the result of that into set watch list and then we're going to pass these down so i'll do add stock and delete stock so now that we have the functionality for adding stock i'm going to go to our autocomplete component and actually it looks like i have an error hold on let me yeah i'm not sure what happened there but i just saved this file again and seems to fix the issue so it doesn't look like there's anything wrong but let's go to our autocomplete component and let's set up that uh use context hook i'm going to say const which i'll just say use context and this is going to be the watch list context and let's just copy the imports from the other one so i'm going to copy this and then we'll import use context and then what do we want we just want to destructure out the add stock and once we get that what we want to do is on the specific li for the result we're going to set up a on click event handler and here we're going to pass an anonymous function that's going to call ad stock and we're going to pass in the result.symbol so this is just when the user clicks on one of the results it's um let me find an actual stock uh when it clicks on this it's going to pass the symbol of that specific company to the add stock function that we get from the use context which will then go to the use context and then i'll add it to the list so i'm going to go to inet we'll search that and then we'll click on this okay and this thing still stays open but that's okay we'll fix that and i don't think it actually worked so let me actually go back to the website okay so let me try this again okay so it looks like there's some sort of issue let's go back to my autocomplete and figure out what i did wrong i did an on click we call ad stock and it looks like i figured out the issue so what's happening here is that when i select anet it is technically getting added to the watch list and i can actually see that by going to my react dev tools and going to my watchlist context provider we can see anec got added but the problem is is that once it gets added if we go to our watch list context sorry our stock list component so this is the component that renders out the table it runs this use effect hook and this use effect hook is responsible for getting the quotes of all of the items that are in the watch list however if you take a look at when this use effect hook runs it only runs when the component mounts so after it mounts it does not matter how many items we add to the watch list it's never going to run again so we want this to run every time watch list changes so all we have to do is just pass that into the dependency so we'll just pass in watch list and so now anytime watch list gets updated a stock will get added and we can see that it already got added in there so that's why it wasn't getting updated so i'm going to refresh this and we'll test this out again so i'll type in a net select it there we go it gets added in perfect now i do want the drop down menu to go away after i select an item so i'll go back to my autocomplete and this on click event handler i'm going to actually remove this shorthand notation i'm going to add in two steps so it'll be add stock again result dot symbol and then afterwards what we want to do is we want to clear out the search and when we clear out the search it'll automatically remove the drop down so i'll say search set search so we're calling that hook right here and we're gonna set the search for our input to be empty and when it's empty the drop down will lose or it'll get the uh extra it'll lose the show class which means it'll be hidden from there on out so let's try this again i'm going to save this select this and we can see the drop down goes away so the last thing that we have to implement from the summary page is the delete functionality so we're removing an item from the list however there's something i want to show you guys when it comes to event propagating within react and the only way for me to show you guys the issue would be to first implement the detail page so we're actually going to take a break from the summary page we're going to the last thing of removing the item we're going to cover that at the end of the project instead i want to move on to the detail page and just to kind of reiterate how this is supposed to work when i select on a stock when i select in a row take a look at the path right now it's the root path i select this it then goes to detail then the name of the stock and then it loads up the detailed page so let's implement that this is going to be done through react router and you'll see that it's actually pretty easy and we made use of the apex charts library to build out the charts and you'll see that it'll actually be dead simple doing that as well so let's go back to our app and let's go to our stock list component and let's find our uh our specific row so when a user clicks on a row we want to call an on click event handler and right now i'm just going to have this call a function and this function is going to be called handle stock select so let's define this function and what we want to do is when we select a specific row we want to tell react router which is our routing library to route to a url of slash detail slash stock name how do we do that well react router comes with a built-in hook that makes it very easy so let's import this hook from react router we'll do import use navigate from react dash router dom and now we'll just do a const navigate equals use navigate okay and so now if we want to go to another path or url we just use this navigate object so i'll say navigate and then all i have to do is just pass in the url that we want to for the user to so we want to go to detail slash and then the stock name so we have to get the stock name so we'll say that um the event handler has to accept it as an argument so we'll say um symbol so the symbol of the stock and then we can just do string interpolation and then just pass in symbol so now when we actually call this when it gets selected we have to pass in the symbol so where is the symbol it's stock data dot symbol i'm just copying what's here and that should be all we have to do actually so let's go take a look okay so if we take a look at the url right now we can see it's at the root url so this is the equivalent of just a forward slash and so i'm going to select google and we can see that it routes to slash detail google and we can see the stock detail page so everything is working exactly the way we expect it however one thing is um i want to be able to get the clicker icon instead of the regular pointer because i want to give the user a little bit more feedback and we can easily do that by passing an inline style and i can just say cursor is set to pointer now can see that we get a pointer perfect okay so let's go to our stock detail page now in our stock detail page the page has to be aware of the specific url because the symbol or the the stock that we want to see detail is in the url so how do we extract that information from the specific url like how do we get it how do we get this value from the url well once again we're going to make use of the react router library and we're going to use a hook called use params so let me import that so now i'll just do const x equals use params so this will get all of the parameters however we don't want all of them i just want the symbol right and that parameter where that comes from the name is going to come from our original route so whatever we passed here where it says detail and then the variable this parameter we can just extract out symbol so here i can destructure out symbol and let's render out stock detail page and then let's just render out the symbol to see if we can actually get that information so now if i select google we can see stock detail page google so we were able to get that parameter for the stock detail page what i'm going to do is i'm actually going to fetch the data within the stock detail page component and then i'm going to pass that data down to the chart component i want to keep the chart component as simple as possible i just want the chart component to be responsible for rendering out the data i don't want it to be responsible for fetching the data so i'm going to have the page actually fetch this information so to do that we're going to make use of the use effect hook again and i'll define my function for fetching data and let's import axios so i'm just going to copy the import from another file well actually i might as well just type it out now we can do a const response equals and then we can fetch our data but we have to find out what data point do we actually want to fetch or what which endpoint do we want to fetch so if we go under stock price you want to go under candles so this is going to return historical data and to get the information you send a request to stock slash candle and then the parameters are going to be first of all the symbol like you would expect then the resolution so what's the resolution if we go down here resolution is going to be what is the gap between each data point that we want to plot so this is um every minute so we'll get a data point for every single minute every five minutes 15 minutes 30 minutes 60 minutes uh one data point per day one per week one per month so if we're going to chart out um you know one day's worth of history we may want to do every five minutes or every minute however if we're going to chart out one year worth of historical data you don't want to do every minute that's too many data points i would instead prefer either every day or even every week so that's what the resolution is then from and to so from is going to be you know what is the earliest time that we should get a data point from and two should be what should be the last data point time stamp from i worded that incorrectly that should be the last time that we should grab a data point from so if we want um one day's worth of historical data the from would be the unix time stamp for exactly 24 hours ago and then the two would be the current time and then if it's a year then the from would be moved back a year and so on so let's go back here and i'll do a weight binhub.get and this is going to be stock candle and then params well we we're gonna pass in the symbol then we need the from the to and the resolution okay so how do we get this information well we're gonna make use of the date object so i'm going to go and say const date equals new date so that's going to get the current date and if or if i want to get the current timestamp i'll do uh const current time equals date dot get time so at that point we can take the current time and pass it into the two because that's the last data point because we want the the current time to however the api i found out and this took me a a quite amount of time quite a bit of time trying to figure this out but this get time returns it in milliseconds the api expects it in seconds so to convert this to seconds what we want to do is we want to divide it by a thousand so that's going to give us seconds and then we also want to do a math dot floor so that's just going to truncate any extra decimals and in fact i think it might actually help if i just kind of lab this up real quick so we'll say const date equals a new date and then if i do a const current time equals date dot get time and if we run node test.js and i should have console logged it now if i run this this is going to be the unix timestamp for the current time in milliseconds if we want to convert it to seconds current time seconds and then we do a console log so you can see that this is now being represented in seconds let's just move the decimal over three places so that's really all that's doing and if we ever want to get like if we want to go get the timestamp for one day ago how would we do that well we can take the current time in seconds so i'll say current time in seconds and we want to subtract 24 hours right that's one day so how do we get to 24 hours well this number is in seconds so we have one second how many seconds are in a minute we have 60 seconds in a minute we have 60 minutes in an hour and we have 24 hours in a day and so this is going to be we'll call this one one day ago so this is going to give us the time for one day ago um how would we do one week ago well we can do which is going to be current time in seconds minus this represents one day we already know that and then we just multiply it by seven because a week is seven days and then what's a year it's going to be a year is just going to be 365. so that's all we got to do to get the to and from time so we have the current time let's get the time for one day ago so i'll say const one day equals current time minus 24 times 60 times 60. and so the from is going to be one day so from one day ago to the current time so the two is going to be current time and then the resolution we can do every 30 minutes and now let's fetch this data and we actually want to do this only when the component mounts so fetch data and then we'll console.log the response okay so if we take a look at the response something interesting is happening it says that data under data it says no data so i'm not really sure what's going on but as a test i'm going to change this to be three days ago and i want to see if this fixes the issue and now if i take a look at the data oh look we get some data back so for some reason if i do one day ago nothing happens but if i could do three days ago something happens and i actually noticed this when i was laughing this out and i only noticed this issue right before i started to record and that is that i'm recording on the weekend this is a saturday well technically it's sunday now um and the stock market's closed on sundays so there's no actual data points for one day ago because if you're on if it's sunday one day ago saturday you're not going to get any data points so this is something to keep in mind so we have to fetch data and get calculate the time uh depending on what is the current day so if i want to get basically just one day's worth of uh of data so if i want to get friday's data well if it's saturday i have to go two days back and if it's sunday i have to go three days back that's all so i have to put in a couple of if statements uh when capturing the time this is just one of the uh kind of the pain points of working with with this kind of data um i didn't even think about this issue when i first coded it out so all we have to do is do an if statement and i'll say if and then we grab date dot get day so this is going to return a number depending on what day it is and saturday it'll return a 6. so i'll do equals equals equals 6. so if this is a saturday then i'm going to make one day first of all is going to be a variable that i can change so it's going to be let if it's saturday then i'm going to do get two days worth of data so i can get friday's data and then i'll copy this and then if it's sunday which is going to be a zero then i want three days worth of data so now our application's smart enough to figure out that hey if it's saturday we're to have to get two days worth of data if it's sunday it's going to be three days worth of data and then if it's not any one of these days and actually this should be in if else i'll say if and let me move that up and then finally else one day is just going to be just one day so we'll remove the three okay so back to our application and now we've got some data so to understand what how this data works is pretty simple so t stands for timestamp so at this specific time this is a unix time and if you ever want to convert this pretty easily there's a lot of tools online like this epoc converter.com you just take the time you paste it in there and then it tells us hey this is uh this is the timestamp of that data point so this is august 25th at 8am so this is the timestamp and then these are the values that we saw before at that specific timestamp so what was the close what was the high what was the low what was the open and what was the the volume i guess so now that we've got this data let's also get the data for one month sorry one week and one year and i'm going to define a variable so i'll call this const one week which equals current time minus 7 times 24 times 60 times 60 and then for one year we'll just change this to 365 and then we can just copy this and we'll change the from to be one week and the resolution to be and we'll just call this response week response day and the resolution can be you know every hour so we just need a data point every hour and then we have response year it's gonna be one year resolution can be i don't know you know every week that would give us 52 data points if you wanted every day you could do every i think it's every day what was the yeah d stands for day so it just depends how detailed you want it to be i'm just going to do one week just because there's no need to grab 365 data points for this demo so this is going to fire off three requests get all that information and then i can just do a console.log of all of these okay and so now we've got uh this is going to be the day this is going to be the year of the week and then this is going to be the year however if you've noticed that this is all happening in series sequentially so this one has to complete first then we send the request for this and then we send the request for this and we can confirm this by going to our network tab and there's a lot of networks so let me actually clear this refresh so notice how one i hated that one complete one one completes then the next one completes and then the next one completes so we don't want that so we're going to do the same thing that we did for the um stock list component where instead of fetching it one by one we do the promise.all method so we could just fire off all those requests at once so here i'm gonna go up here and i'm gonna do const responses equals await promise.all and then we provide a list and i can just copy these into there and then we can just do a console.log responses all right and we see all three fired at once perfect perfect perfect and i think something's actually erroring out hold on let me see if i can find this out so let me put this in a try catch block which we should have done anyways okay never mind okay all of them are in there that's good everything's working now the next thing that i want to do is i want to format the data because if we take a look at the data this is not exactly in the most convenient format because this is still the axios response so it's got all of the extra config information that i don't care about it's got the headers the request i don't care about that i want the data but in addition to wanting the data i also want to format it a little bit differently and the format that i actually need this in is going to be a little unusual but you can see right now we have a object and then for the closing value it's a list of all the values and then for the t is going to be a list with all those values and so the first item in here matches up with the first item here with the time step here the second one second one and so on and instead of doing it like that i need it in a specific format for my chart and i want the data to look like this so i'll say constant data and it should be an object with an x value of the t value of the t right that's going to be you know this here and then the y should be the closing value so what was the closing value at that time and then i want a list of these so it would actually be a list and then i would have a couple of these so that's that's what i want the data to look like so we're going to have to transform this data ourselves and let's define a use state hook so that we can save our data so i'll say const we'll call this chart data and then we have set chart data equals use state and i showed you what we wanted the the data to look like and i'm actually going to save that in a file actually don't worry about that and actually what i want to do is i want to store in our um in our in our hook in our chart data i want to store it like this so in our cons chart data it should look like this we should have an object with a property of day and this is going to have data for one day and then we'll have a week and then we'll have a year of data for a week data for year so that way our chart can just pick whichever one it wants and then the date the data for each one of these should be the way i showed you guys so that was the data equals object that's going to be a list an array with uh multiple objects with an x of some value and a t and a y of some value and there's going to be multiple data points so that's what i want the data to look like so this is going to go in the value here so hopefully this makes sense this is kind of the most confusing part is just manipulating the data for the chart but i want to get it into that format so down here after we fetch the data i'm going to call set chart data and we're going to pass in the object with the day property with the week property and the year property and we're going to call a function which we're going to define in a bit format data and here remember the responses for the responses the first one is going to be for the day the second one is for the week and the last ones for the year so i could say responses and then we want to grab zero so the first entry and then within the zero we want just the data right we only care about the data we don't care about the configs so i'll say data we're going to do the same thing for the rest of these guys and then this is going to be 1 is going to be 2. so let's now define this uh function outside of our component we don't really need it in the component so it's going to receive some data which is going to be an array and guess what we're going to do we're going to do uh the map method so say data dot and so right now we're getting this data object right here so we want data dot and then we want to iterate over t t dot map and we'll get access to two things now you know normally when we did the map method we get access to just one which is the element that we're iterating over but we can actually get another value which is going to be the index of the item that we're iterating over so i'll grab the index and so i'll say return so x is going to be the element so that's going to be the specific time stamp right so this could be this time stamp but we have to multiply it by a thousand because uh the the api does it in seconds and unfortunately our chart does it in milliseconds so just multiply by a thousand and then we have to get the corresponding y value right so for the first item in the t array we want the first item for the c array so we just say whatever index we're on just grab the same one from c i'll say y data dot c index and that's all we have to do and let's refresh this responses is not defined let's take a look at where that is oh yeah that's silly me so we're going to move this into our try catch block now if i go into my react component extension and we go into stock detail page and we take a look at our state our state looks exactly the way we expect it to look so we've got one for day with x y we've got one for week with the x y coordinates and then the y and then the year perfect and for the dependency array um technically this will work the way it is however if the symbol changes we should run the use effect hook again so we're going to add this to the dependency array and for returning data uh we're going to do a couple things first of all let's create our chart component so i'm going to call this add file we'll call this stockchart dot jsx and i'll say export const chart and then in our stock detail page under this div i'm going to actually do two things so first of all we don't want our chart to render until we have our chart data set so if it's still fetching data we don't want to render the chart because there's nothing to render so i'm going to say if chart data and then i'm going to do and and and render out a div and then within our div i can call my stock chart component and we'll import our stock chart component and so what exactly is happening here this is a nice way of saying if chart data is not null then i want you to render out this data if it's not if chart data is null then it's going to return null and it's going to render nothing so it's basically just doing a little if statement if chart data is a value we'll render this out if it's not then nothing will get rendered out so let's test this out no errors and you can see it loads up there's nothing there and then stock chart comes up after we get chart data perfect okay so let's work on our stock chart component the first thing is we're going to receive some props and mainly it's going to be the chart data so i'm going to destructure that out and then when i actually call this in my stock detail page we're going to have to pass in that data so i'll do stock chart then chart data equals chart data and i think we should also pass down the symbol because the chart should know that as well so i'll pass down the symbol and now in our stock chart what we can do is we can destructure out the day week and year from the chart data and now it's just a matter of configuring the specific chart library so we're going to make use of a charting library called apex charts so let's go to the documentation in here and so all we have to do is do an npm install apex charts so we can go back and i'll go here and i'll search for apex charts and we want that first result and in addition to that if we go down to integrations they have react integrations that make it a little bit easier to work with the charts and so we have to install a second library which is kind of like a wrapper for the apex charts library to work with react so that we don't have to do all of the hard work ourselves so this is just called react apex charts and i will install that as well and if we take a look at the react integration all we have to do to create a chart is just pass in the chart component that comes from react apex charts and it requires a couple of things first of all it's going to be options so this is like the uh configuration for your chart like what color do you want it how do you want it to kind of operate animations things like that series is going to be the data that it should receive uh the type that's going to be the type of chart and then also the size of the chart as well so only four props that we need and we'll go over all of these props in a bit and let's go to chart types and the chart type that we're going to use is called an area chart so this is going to be what we're using and if we just take a look right same thing so we know what we're going to set the type to um if we take a look at what else do we need okay so using the chart when we pass the series like i said the data should look like this right the x is going to be the time and the y is going to be the value or the price of the stock and we already configured that ourselves so we're already good to go on that that's why i format it ahead of time the other properties that we need is the x-axis should be set to type of date time so that's going to give us the time so let's just go ahead and just start playing with it and then just work on this one option at a time and so i'm going to import chart from be act apex charts i'm going to render out a div and let's define the options for our chart so we'll do const options so first of all let's give our title our chart our title and so if the configuration for the title first of all it's going to be the text what do we want the text or the title of the chart that's going to be the name of the stock so we have the symbol that we can just pass in we have to destructure that out from props so the text is going to be set to symbol align so how do we want to line up the text so it's going to be center and then we're going to make it just a little bit bigger so we'll set style and we'll do font size 24 pixels uh the next thing is going to be chart specific configuration so we're going to give this chart an id so we'll say stock data and then if you want you can also customize the animations and i'm just going to set this to be speed of 1300 next thing is going to be configuring the x-axis so we saw that in the documentation we have to set that to be date time because the x-axis is going to represent a time so type date time so let's try this out i think that's enough options let's set up the series so the series which is going to be the data that we passed to the chart is going to be an array and then an object for the configuration the reason it's array is because if you go back to the documentation you can have multiple series so multiple you know different types of data sets we just have one we just have one so that's why it asks for an array but we're only passing in one object and in this object we have to pass the name so this is going to be the symbol and then the data which is going to be day we're going to set it today for now just to take a look and now i'm going to add some style to this div to set the background color and we'll also give it some extra classes so add some margin to the top some padding shadow as well background is going to be white and i guess i didn't actually need this style we can actually delete that all right now we can pass in the chart component and so the options that's going to be set to that object that we created called options and the series is going to be set to series type is going to be set to area and width is going to be set to 100 percent okay and we can take a look at our chart and it actually looks pretty good so it's able to plot the data points however right now it's not using the correct uh time and that's because i wanted to show my local time so wherever i'm located i'm located on the east coast i wanted to show the east coast time uh and then when you know when you guys are using i wanted to show your local time and so to do that we can go up to x-axis right here set labels date time utc that defaults okay and that's better so that's better now if you take a look at the the tool tip right it says 25th of august i wanted to be a little bit more detailed i wanted to include the specific time stamp as well in the tool tip so we can go under x-axis here and add a tooltip configuration and the format i want this to be for the x-axis is going to be format and then we want mmm for the month the day and then i want the hour and then the minute so now we got the month day and the time as well the next thing that we need to implement is we have to provide the buttons for the users that they can select if they want to see uh the past 24 hours if they want to see seven days or one year's worth of data and we should be able to change between these and also obviously the color changes depending on if the stock gained or if the stock went down so going back to our app we're going to render out a couple of buttons right under the chart so i'm going to add another div and we're going to add a couple buttons and these buttons are gonna manage you know which one they've selected so we're gonna have to use uh we have we're gonna have to define some state we're gonna use the use state hook and i can call this uh what about i don't know date format i couldn't think of a better name and then set date format use date and then it's going to be 24 hours okay and so uh when the user wants to see one day's worth of data they're gonna set date format to 24 hours uh if they want to see um you know seven days we'll do seven days and if they want to see uh one year they'll say one year and so for these buttons we'll just set up a on click event handler and we'll say set date format to be uh the first button this is going to be for um one day so i'll say 24 hours and actually let me add the closing tag as well so now i can say 24 hours and i can copy this on click event handler and just paste it into the other two and just change this to be seven days and one year and then don't forget to import the eustate hook and so now we have these buttons and obviously we can add some style to them but now what we want to do is we want to update the data depending on which one is selected whether it's 24 hours one week or one year and i think the best way to do this is to define a function i'm going to define a function down here it's going to be very simple it's going to be called determine time format and we're just going to have a switch statement where we're going to switch on date format which is going to be the use date hook that we just created so whatever this is and if it's set to 24 hours we're going to return day so we're going to return the data from here and if it's seven days then we're going to return week and if it's one year we're going to return year and then we also have to provide a default and so if nothing is provided then we'll just return day as well and so now inside this series we can just change this to be determine time format we just run that it's going to return the correct data set so if i try seven days we could see it adjust one year and for the year we can see there's something goofy going on and that's because it added a lot of decimal values i think i remember seeing that also let me see if i can find that in the actual data set yeah so this data point right here so we're going to have to truncate it maybe we'll just grab you know two decimal points and so to fix this issue um what i'm actually going to do is if we go to the stock detail page where we fetch the data and then format the data when we format the value you can perform the truncation here so you know i said i was going to round to two i was going to keep two decimals but i think it's just easier just to remove the decimals so i'll do a math.floor and that's going to remove all the decimal points if you want to handle the logic for keeping two decimals you would just manipulate it right here yep and now we can see we just get whole numbers perfect all right so let's style these ugly buttons and on top of that let's also provide some feedback to the user which uh which one they've selected right if we take a look at the final app it highlights the one they've selected and to do this if we go to our stock chart we go to our button component for styling purposes what we want to do is add a couple of classes we want btn and btn-primary and that's going to give us this look and if we do btn outline dash primary right now we have the unselected look so that's the difference between selected and unselected is going to be this outline right here so how are we going to do this well i i think we should create another function to kind of handle this logic so i'm going to say render button select so this is going to handle all the styling as well as figuring out which button has been selected so all of the buttons are going to have the following classes they're going to have btn and then i'm also going to add a margin of 1 so they have a little space and then what i'm going to do is i'm going to say if button equals equals equals date format then we want to return classes plus btn-primary and i want to actually add a space here so what this is saying is if this button is um matched up with the selected button or the selected data set then we want to do btn primary which is going to give us the filled in color or else we will do the unfilled in one so we'll do return classes btn outline dash primary and so for each one of these buttons um i'm going to change the class name and we're going to just render that by calling render button select and then we're gonna pass in you know since this is the button for one day i'm gonna say 24 hours we'll copy this paste it to here this will be the seven days and this will be the one year and so what's really happening is um we're passing in one year so we're calling in uh we're calling in uh render button select into this button so button is gonna be set to one year and it says if one year equals equals date format which is whichever one is currently selected then we are going to make that the selected button however if they don't equal that then it's going to be the unselected button i think that should be everything that we need to do so we can see 24 is selected if i select one year one year selected seven days seven days perfect and the last thing that we got to do is we want the color to change based off of if the stock is going down or if it's going up so in this case it's going down it's red down red however it goes up that's green and this gets a little tricky but the colors can be specified in the options so here we would do colors and then you would provide an array and then here you would just provide your you know your hex color okay so uh we're going to first implement the logic for determining are we going down or are we going up this is where the math gets a little funky so i'll say const color this is going to be the color that we want equals so how do we figure out if the value is going up or down so to figure out how to do this i actually want to take a look at the data one more time so take a look at stock not stock chart chart data so we can better figure out what this is going to look like okay so this is what chart data looks like we can see that we get one for day week and year and the logic is going to be the same regardless of which data set we select so remember this is going to be the earliest uh this is going to be the uh first data point so if it's one year if we select one year this is going to be one year ago and then the last data point is going to be the current time so to figure out if the stock has gone up or down we take the current time the current y value and we subtract the first y value if that number is positive that means it went up if we if that number is negative then our stock went down simple as that and we have to do this for all of them so i'm going to define a variable called color now this also has to be aware of uh the the different um day week and year formats so we don't actually know which one selected so we have to run determine time format so that's going to return either day week or year depending on whichever one selected so this function will return that data set and the first thing that we want to do is we want to grab the last item in that array how do we do that well we can call that same function call the dot length and then subtract 1. so that's going to grab the last the last entry right so that's going to go all the way down and it's going to grab well this is the wrong one but that's because since we're typing this out there's going to be errors but that's going to grab the last entry and we want to subtract the first entry so we just run that determine time format we want to grab the first entry which is 0 and then we grab the y value and i forgot we should grab the y value on this one as well so hopefully that made sense all is doing is grabbing the last data point and subtracting the first data point and it's going to use this function to figure out which data set to work on so now we have color or now we have a boolean and we can use a ternary operator to say if it's positive if this value is greater than zero we're going to return this but if it's not greater than 0 then we're going to return this nasty red and then here we can change the colors and just pass in the color variable and i made a mistake i'm going to move this or actually i won't move this i'm going to move this determine time format function above this because it's referencing that so it needs to be above it now we can try that looks like things are working let's try seven days one year okay well they're all going down so let's uh let's go back and find i think what was the one we were looking at okay so that's going down it's red good red green perfect so now let's implement the uh delete or remove functionality so we should be able to hover over one of the rows and then remove it from the list and like i said i wanted to save this until we got the detail page working so that i can show you a little issue that we're going to run into and i was trying to figure out the best way to kind of implement a kind of a delete button or icon and i kind of got lazy so i just picked the simplest way so if we go to our stock list and you go down to the bottom where we render out the data all i'm doing is just adding a button in here i could have picked something a little bit classier but i was just the the idea is that we want to implement the logic that's what matters uh and so the logic is gonna be same regardless of what is the icon you use and where you put it so we're gonna put this button here this is going to say remove or delete whatever you want and let's give this a couple of classes so i'm going to say class name equals btn btn-danger btn-sm ml-3 and then d-inline-block and then we also want to add in a separate class called delete dash button so all of these come from the bootstrap library except for the delete button we'll implement this ourselves and so now we go back there's a remove button however we only want to show this when the user is hovering over the specific row so how do we do that well i'm going to go to our app.css i'm going to define some rules so i'm going to say we're going to reference that delete dash button and i'm going to say visibility by default is going to be set to hidden and then i don't think this is going to do anything but i see this in my notes so we'll just add it anyways then when we hover over a row we want the button to show so this gets a little tricky so we want to say when table dash row and if you recall what table row is we got to go back to stock list and table row where is it here we go table row right here so this class that goes uh assigned to the specific row when table row is hovered we want to select the delete dash button and then here all we do is just set visibility to visible simple as that and now if i hover there you go now we got the remove working so the next thing that we have to do is set up the uh the on click event handler so here's our button i'm gonna set the on click so here we're going to call the well we're going to have to grab the delete stock from our context so we'll call it delete stock and if you forgot where that's coming from that's just coming from our context api where we have this function that we're passing down that handles deleting it from the watch list so we'll say delete stock and then we want to pass in the symbol which is going to be accessible through stock data dot symbol and i think that should be it so let's take a look i'm gonna try to delete microsoft if i hit delete okay well something interesting happened it routes me to the next page so why is that happening well think about this when i click on this delete button technically i am clicking on this row on the row that this button is assigned to so if i go up to this row well where's the row i think i scroll too far the row this has a handle stock select uh on click event handler and if i go to handle stock select that's what handles the navigation so what's happening is when i click the button it's also triggering triggering this on click event handler and this is the issue that i wanted to show you guys so what's happening is that i do technically click on the remove button however the event bubbles up so it starts bubbling up all of these elements up to the to the tr and then it triggers this event handler or this on click event handler so that's the problem it's due to event bubbling so how do we avoid this well react gives us a handy thing we can call so we have to first get access to the event so i'm going to pass the event into the function and we just say e dot stop propagation so this is going to prevent the event from bubbling up to that parent component and this is apparently an a i've been mispronouncing it so now let's go back let's see can i remove microsoft perfect and you see microsoft got removed can i remove google perfect perfect and that's all we had to do for handling the deletion of an item from that list the next thing i want to do is implement the stock data component which is going to give out some extra information about the company uh like what was its ipo date what's the you know what's its market cap what's its website and things like that so let's go back to our components and let's create a new component and it's going to be called stock data we'll do export const stock data now the way that stock data works is that it's going to fetch data from a new api endpoint and i believe it's called company profile2 and so yeah this is the one that we want to use so we just send it to slashdoc profile2 and then you provide the symbol and it's going to give us all of that information that's all we got to do so let's handle fetching all the information and this component is actually going to accept a prop which is going to contain the symbol of the stock that we want to get information for so let's import the use date and use effect hook and then we'll call the use effect hook and let's go ahead and set the dependency array this is going to render anytime symbol changes anytime that prop changes and then we'll do const fetch data and let's import the api as well and i'm going to go a little bit faster for this um you guys have already seen this enough time so should already be second nature but here we can fetch the data and i'm going to do uh let's get the try catch block and so this is stock and then profile two and then the params is going to be the symbol only and if we go to our detail page we want to render this component out in the detail page and so i'm going to just render it right out right below the stock chart so let me import it sorry this should be stock data and i got some errors let's see and i actually already know the error so this should be apis okay and let's take a look at oh it doesn't look like it rendered out or no we need to i think i forgot to console log it no i logged that console logged it yep and i forgot the parentheses okay so we got that let's try this out now all right and so now we have all of the information about the company and so we can render that out now and that's really all this component is doing is just fetching a little data and then rendering it out but we do have to store this information in a use date hook so let me just do a const stock data set stock data that should be in the use effect hook and then right after here we'll say if is mounted then we want to set stock data to be response dot data and then we'll add the cleanup function and now it's just a matter of rendering rendering out um all of that data so this is now going to be changed to a div and i'm going to do that same expression where i say stock data if that's set and only if that's set will we then render out the rest of this and what we're going to render out let's see we'll start out with the div and we'll give this a couple classes so i'll say row border bg dash white rounded shadow dash sm p dash 4 and mt-5 and then within here we're going to have some divs this is going to have a class name of col and there's going to be three of these and then within each of these there's going to be three entries for the individual data points so i will say and let me not copy that i think that might confuse you guys so we'll say div and in this div we're going to have a span with the class name of fw bold and we're gonna have three of these within each one of those parent divs under call so i'm gonna add three in there and three in here and now we can just name the property so this one's going to be name this one's going to be the country this one will be the ticker this one will be the exchange we have the industry the ipo market cap shares outstanding and the url all right so now if we check this out and go back to the main page and okay so it's got all of the headers but it's not spread out the way it should be so i feel like i'm missing a class or two okay yeah i just had a uh a minor typo um that got messed up with the divs but now it's spread out across the three uh the three columns that i've defined and now it's just a matter of passing in that data into each section and we already have the different properties so if we want country we just do country currency exchange and so on so i'm just going to quickly go through this we have the stock data stored in this variable and we can just access it through that property so we'll say for the name we'll just do stock data dot name and i'm going to just copy these real quick across each one of them and then we'll update it individually we have the name the next one is going to be the country this one will be the ticker this one will be the exchange this one will be fin hub industry next one will be ipo and we have market capitalization share outstanding and then this last one is going to be a url to their website so i'm actually going to make this a a link and the href is going to be stock data dot web url and then for the the text you can make it whatever you want i mean you could just do the same thing if you wanted to just make it stock data.web url and let's give some spacing between these like i did for the other ones and i think that should be everything that we need here we go so that's going to wrap up the stock data component so the next feature that we need to add for this project is let's say that the user navigates to our website the first time we automatically populate these three stocks for them um and then let's say they go in and they search for a specific stock and let's say they want mcdonald's and then let's say they delete one of these other stocks if they navigate from this page or refresh the page guess what happens our website doesn't remember and it goes back to google microsoft amazon if you take a look at the final product the final product will remember uh any stock that we it remembers our entire watchlist so if i grab mcdonald's and i delete google i hit refresh it remembers it and the way that it does this is if we go to the chrome developer tools and we go into application and you go under storage local storage you can see that what i have done is i have stored the list of stocks that the user wants to keep track of in storage in local storage so that when we populate the website the next time they visit it we could just pull this list and then query that data so this is the next feature that we're going to implement and you're going to see that it's actually going to be pretty quick and pretty easy so this is all going to be done in the watchlist context because that's what handles the watch list and i'm going to import a use effect hook i'm going to add a use effect here and i want this hook to run whenever we change watch list so anytime watch list changes i want to go to local storage and then i want to set something so i'll do set item and the key is going to be called watch list and the data we're going to pass it is going to be our watch list now this use effect hook is going to run every time this provider component re-renders we don't really want to do that we want it to render every single time the watch list gets updated so we just say we set the dependency array to be watchlist and this really is the main use case for use effect so anytime something changes in your application and you want to update something kind of outside of your application like the local storage or a session um or some other property outside of your application you use a use effect hook and this is the perfect use case so this is going to set it and i think i forgot a t wait item so let's test this out so i'm going to add in tesla and now if i go to my application tab and we go to local storage we can see google microsoft amazon tesla so now if i refresh it remember well it didn't actually remember it but that's because we set it in our local storage however it's not actually pulling that information from the local storage so where do we actually where and when do we pull this from the local storage well it's going to be in this u-state hook so when this u-state hook runs the first thing it should do is and i'm going to copy this for a second and i'm just going to paste it here make this a comment and i'm going to put this across multiple lines so when the the default state for our hook should be when our application first loads we should look into local storage and we should call get item for watchlist so this is going to give us a string and if we actually take a look at it it just gives us this string so we have to turn it into an array so how do we turn it into array we call a dot split method and we want to split it every time we see a comma and if we don't have anything in local storage then we're just going to default to this does that make sense right remember this is just a string when you read and write to local storage it's just a plain string right and so when we call the split method it's going to split it wherever there's a comma and it's going to add that as an entry into a list so let's try this out now i'm going to add tesla okay tesla's in there let's refresh and it remembers tesla let's remove microsoft does it remember that it does in fact remember that and keep in mind i have to refresh this so if i yeah we could see microsoft's not there now i'm going to show you a bug in our application if i go to my watch list and delete it and i hit refresh nothing shows up what's going on well let's see if there's something in the console and we can see the air says cannot read properties of null so what happened well our application loads the provider loads and then it runs this uh you state hook where it sets the default value so it does so it looks into local storage it tries to get item watch list keep in mind if we go to our application in here we can see there is no watch list so this returns nothing and if you try to uh this returns undefined and if you try to perform a dot split on an undefined that's the exact error that we're getting right cannot read properties of null reading split we can't we can't call split on null so how do we get around this issue very simple you just put a question mark right here so what this question mark does is it's going to check to see if this actually exists if it doesn't it's just going to return a null and it's not going to run this code i think this is called null coalescing i can never remember the terms but yeah so all this does is check to see if it exists if it exists perfect we'll just run the next code if it doesn't exist it's going to return null and if this returns null then we just default to this so let's try this again okay and look at that it defaulted to the three despite the fact that we had cleared the local storage and we can just test this out once again and that's perfect so it looks like it's working i'm going to remove this stack overview page we don't need that let's see where is that stock overview okay guys so that's going to wrap up this project we've implemented all of the features uh that i wanted we've gotten a chance to learn a lot of different features and functionalities within the react ecosystem things like the context api react router we've gotten a chance to work with different libraries and apis like the apex charge library as well as the finhub api and uh hopefully you guys enjoyed this project and i will see you guys in the next one we've reached the end of the course not only have you learned the basics of react you also coded three react projects good luck to using this knowledge to create your own react applicationsreact is one of the most popular front-end javascript frameworks and this beginner's course is the perfect way for you to learn how to use react this course is unlike most of the other react courses out there today instead of just a single teacher we've brought together an all-star lineup of instructors to teach this course these three instructors are some of the most popular instructors on our channel and have received well over 10 million views on other tutorials learning from a variety of perspectives can help you solidify your understanding of key react concepts this is a project-based course and it focuses on teaching you everything you need to know to start creating your own react applications first gavin lawn will start from the absolute beginning and teach you the basics of react through building a simple single page application to keep track of team members gavin has been a software developer for over 20 years and he's great at passing down the wisdom he's learned over the years next you'll learn how to make a meals app from john smilga john is one of the most viewed instructors on our entire channel so you're definitely in good hands for this second project he'll teach you how to fetch data from an external api to use in this react application finally you'll learn how to create a simple stock trading app from sanjeev thiagarajan you'll use what you've learned so far and apply it to an application that gets data from an api and stores data to local storage among other things sanjeev previously created one of the most popular and comprehensive api development courses in the world so he is the perfect person to teach you more about using apis with react and to follow along with this course all you need is a web browser every project in this course is developed using the replit online ide replit provided a grant that made this course possible so we're about to get started but let us know in the comments what you think about courses with multiple instructors hi and welcome i'm gavin lon i've been developing software professionally for many years and i'm really excited to bring you this react for beginners course i hope you enjoy it and i hope you benefit from it i've developed a very basic spa application single page application using react that we'll create in this video while we create this application we'll cover basic concepts in react let's take a brief look at the react application that we are going to create so let's say that we are a developer in a software development company where a lot of contract developers are employed on a temporary basis and assigned to their relevant teams depending on the current projects being developed by our organization team members are moved between teams on a fairly regular basis depending on the current projects being developed by our organization so the team member agility as it were is great but keeping track of who belongs to what team can be difficult for our development manager at times the development manager has asked us to develop a basic spa application where he is able to use the application to allocate team members to their relevant teams and can use the application to keep track of the teams and team members on the home page you can see that at the top here we have a drop-down list that contains the names of the teams in our development department below the drop-down list we have a number of cards displayed in a tabular format each card represents an employee the cards that have a dark box shadow surrounding them are the team members that belong to the team currently selected in the drop down list you can see at the top of the page status is presented to the user displaying how many members the selected team currently contains the count of the relevance team members in the selected team changes dynamically and appropriately as the selected item in the drop-down list is changed the user is able to add a new member to the selected team by simply clicking on a card that does not have a dark box shadow surrounding it once the card is clicked a dark box shadow appears around the relevant card and this means the relevant employee represented by the card is now a member of the team selected in the drop down list as a new member is added to the team the count of team members displayed to the user and the status message at the top changes accordingly we have a navigation menu at the top of the page we are currently on the home page where we are able to add team members to teams and remove team members from teams the user is able to navigate by clicking the team's menu option in the top navigation bar to a page that displays the teams and team members in a collapsible list the user is able to click each team name represented as headings in the collapsible list to reveal the list of team members that belong to the relevant team when the user navigates back to the home page the team that was last clicked as it were in the teams page will be the selected team in the drop down list and the user can then add or remove team members from the selected team when the user clicks a card on the home page that already has a dark box shadow meaning that this card represents an employee that is part of the selected team this action will remove the employee from the selected team the result of this action is represented on the ui by removing the dark box shadow from the relevant card so the cards can be toggled whereby the employee that the card represents is added to the relevant team through a click action and is also removed from the relevant team with a click action we are going to develop our spa application using replit replics is a popular free collaborative in-browser ide where you are able to code in 50 plus languages without spending much time on setup so in order to create our react application using replit you'll need to sign up for a free account with replit it's a very simple process where you are able to use your google github or facebook account to sign up for your free replit account or you can simply provide a username email address and password to sign up for your free replit account for details on how to create your free replit account please navigate to this url so you can see here i've logged onto replit and you can see that i've created a few rebels here rebel stands for read eval print loop in a bit i'll take you through a way in which you can create a rebel through raplet but for more details on ways in which you are able to create a reply using replit please navigate to this url so before we create our repl let me open a repel that i created earlier that can be seen as the prototype for the react application that we'll create in this video the finished code for this application is available on github at this url so before we leap into writing code what is react react which is sometimes referred to as a front-end javascript framework is a javascript library created by facebook react is a tool for building ui user interface components how does react work very basically react creates a virtual dom document object model in memory react is very fast react finds what changes have been made and changes only what needs to be changed so let's create a repel for our react application to create a rebel we can click this create button here you can see in the drop down list we have a number of programming languages and developer platforms that we can choose from but we want the react js item in the title field we can name our repo whatever we choose i'm going to name my reple team member allocation then let's press the create rebel button great and our environment is set up for our ripple it's that simple we can now build our react js spa application let's quickly create the traditional hello world application and look at that when we change the output in the app.jsx file it is immediately reflected in the output of our application before we get started building our application let's remove the default css code in the app.css file this is the file where we will include all of our css code for layout and styling purposes we are also going to use bootstrap 5 for layout and styling purposes we'll look at how we are able to integrate bootstrap 5 into our application a little bit later so let's create three ui components using react these ui components are represented in jsx files i'll explain what jsx is in just a bit so let's create a jsx file named header.jsx like this let's create a jsx file named content.jsx and let's create a jsx file named footer.jsx let's create the code for our header component in this video i'm going to teach you the modern way of developing a react application which uses functional components rather than class components for more details on class components and functional components in react please navigate to this url i'll represent our functional components using javascript arrow functions so for example a javascript function can be represented using this syntax you can also represent the same function as an arrow function using this syntax if the function contains parameters the arrow function representation of this function would look like this for more details on arrow functions please navigate to this url all the references to links in this video can be found below in the description of this video so the code for the header component simply outputs this html code to the browser we are now able to reference the header component in our application declaratively by appropriately including a header element within the app.jsx file we first need to import the header component into the app.jsx component to do this we can include this line of code at the top of the app.jsx file like this and now we can include the relevant header element appropriately within our app jsx file great let's take a quick pause and look at the structure of our react application if we open the index.html file you can see that we have a div element with an id of root we also have a reference to the index.jsx file within the index.jsx file the container const is referencing the root element you can see here the render function is being called to render the app component within the root element so let's create the code for our content component to get the basic structure for a functional react component let's copy the code from the header component and paste it into the content.jsx file and appropriately change the code to suit our content component let's do the same for the footer component let's write code to import the content component and the footer component into the app component let's appropriately include the content element within our app component and let's also appropriately include the footer element within our app component so as mentioned earlier we are going to use bootstrap 5 for styling and layout purposes in our application we are easily able to install bootstrap 5. so to do this let's click the icon here representing packages let's search for bootstrap and this is the package that we want to install to install this package let's click the plus icon here great to have access to all the bootstrap 5 classes within our react application we can include this import statement within the index.jsx file like this to double check that our bootstrap package has been successfully installed we can open the package.json file great to test that bootstrap is working as expected let's include a few bootstrap classes within our h1 element in our header component great notice here that i've used the class name property within the h1 element rather than the class property in a plain html web page you would use the class property for this purpose to reference a css class or classes in a react application we must use the class name property for this purpose because the class keyword is used in javascript class is a keyword in javascript and jsx is an extension of javascript that's the principal reason why react uses class name instead of class for this purpose so what exactly is jsx jsx stands for javascript xml jsx allows us to write html in react jsx makes it easier to write and add html in react it is just an xml like extension that allows us to write javascript that looks like markup and have it return from a component so within the component we have here the return keyword the code that the component returns is jsx code that represents the markup that we are returning from the component it's important to note that jsx is not valid javascript so browsers can't read it directly so what's known as a transpiler translates it to react dot create element calls transpilers a compiler that translates one form of syntax to another like babel or typescript compiles the jsx into appropriate syntax that browsers can understand let's remove these bootstrap classes here and start to develop the functionality for our application let's create a file named employees.jsx let's copy the basic code structure for a functional component created in our header component and paste the code within the employees.jsx file so let's write code to import the use state hook into our employees component we can do this with this line of code i'll explain what a hook is in react and the functionality made available through the use of the used state hook in just a bit we are using the use state hook in this case so that react can track the state of an array of objects that contain details about our employees so we can set a default value for our use state hook by passing in an appropriate argument to the hook here so we want to pass an array of employee objects to speed things up a bit we can copy the code for the relevant employee array from this location on github and appropriately paste it into our code here like this so let's look at the code that we have just created regarding the use state hook and let's understand the purpose of the use state hook if we navigate to this url the react docs describe hooks as follows hooks are a new addition in react 16.8 they let you use state and other react features without writing a class you can see here in an example where the use state hook is used within a functional component the equivalent functionality can also be achieved using classes but of course the code is different when using class components when compared to how we write the code using functional components a hook is a special function that lets you hook into react features for example use state as a hook that lets you add react state to functional components so when would i use a hook if you write a function component and realize you need to add some state to it previously you had to convert it to a class now you can use a hook inside the existing function component what does calling use state do it declares a state variable our variable is called employees but we could call it anything this is a way to preserve some values between function calls use state as a new way to use the exact same capabilities that this dot state provides in a class this javascript syntax is called array destructuring it means that we are making two new variables employees and set employees where employees is set to the first value returned by use state and set employees is the second so basically the first item is the employee data the state of the employees data is maintained in this item the second item is a function reference and is used wherever we need to change the state of the employee's array stored in the first item here so basically the use state hook returns a pair of values the current state and a function that updates it when the state of the employees array changes through a call to the set employees method our employees component is re-rendered to the user's browser the markup jsx code that we'll write in a bit denotes the html code that is re-rendered to the browser so i'm going to quickly demonstrate writing code within the employees component to output a list of each of the employees full names to the screen you don't need to follow along with this part of the video as this is just to demonstrate outputting the relevant markup from our component to the user's browser let's write code to import the employees component within the app component let's replace the content element here with the employees element great so we of course don't just want to output a list of employee names to the screen we want to output the employee details within cards to provide a better ux user experience before we create the code for this let's upload two images that will be appropriately displayed in our employee cards let's first create a folder named images where we'll house our images that we are about to upload you are able to download the relevant images from this location in github you are then able to upload the images like this we can then drag and drop the images into our images folder like this great let's write the code to output the employee data as cards to the ui firstly let's import the image files like this into our employees component notice how when returning jsx code the markup related code must be contained within one element one element must be returned from jsx code if you wanted for example to return the p element and the image element without wrapping these elements in for example a div element react allows you to wrap the relevant elements in empty tags like this in our case we are going to return markup that is wrapped in one element let's write code to return the relevant markup from our employees component note that we are using semantic html here so instead of just using a div element here we are using a more descriptive main element here for layout purposes let's set our main element's class name property to the bootstrap container class for layout purposes let's nest a div element within the main element let's then nest another div element within the development that we have nested within the main element let's set the class name property of the first div development to a bootstrap class that denotes a new row in our pages layout let's set the class name property of the div element we have nested within the row development to a bootstrap class that denotes a new column so i'm using relevant bootstrap classes for these div elements appropriately for layout and styling purposes i won't go into details of these bootstrap classes in this video because i want to focus on react please navigate to this url for more details on the bootstrap grid system we are using javascript's map method to map the data for each item in our employees array to appropriate markup code that will render a card for each employee in the employees array great our cards are displayed as expected to the screen let's center the cards using these bootstrap classes here great i want three cards to be displayed per line so i'm going to use the css grid for this purpose so let's wrap the cards in a development let's set this development's classname property to a class that we'll write in just a bit named card dash collection let's open the app.css class and include the appropriate code for our card dash collection css class so we are setting the display property to grid here and then appropriately setting the grid dash template dash columns property so that each row of cards contains three cards on the ui excellent let's use an appropriate bootstrap class to create an appropriate amount of space around each of our cards this bootstrap class is simply appropriately adjusting the margin property of each of the cards great that looks much better we want the user's mouse pointer to turn into a pointing hand icon when the user hovers the user's mouse over a card we can ensure that the appropriate style of the user's cursor pointer is applied by including this code within the relevant div element that represents a card note that because this is jsx code and not typical html code we must set the style property within the relevant div element to an appropriate javascript object that represents the appropriate css code rather than the literal inline css code that we would apply if we were just writing html code in the case of javascript objects like this it can be confusing for react beginners because you have two curly braces one for the jsx and one for the javascript object notation one of the great things about jsx is that we are able to include javascript logic within expressions to determine what markup code we want to render for our components so we can use curly brackets to tell react as it were that the code within the curly brackets contains javascript logic within the javascript logic we can return html markup related code so let's write a javascript expression that uses a ternary operator to evaluate the gender property of each employee based on this property's value an appropriate image element is returned from our javascript logic great let's create code to output a drop down list containing our teams so for the sake of the example i'm just hard coding the teams in the real world you'd likely retrieve the data from a database through a call to for example a restful web api component great but the select list or drop-down list could look a lot better a really simple way to make our drop down list look better is to use these bootstrap classes great so whenever the user changes the currently selected item in the drop-down list we want this to change the state of our component so to do this we are going to once again use the use state hook so here the selected team variable will store whichever team is selected in the drop down list the second item set team is a function that we can use to change the state of the selected team variable when the set team function is used to change the state of the selected team variable our component will be re-rendered so when our component is first loaded our component is rendered when the user selects a new item in the drop-down list our component will be re-rendered this is because whenever a user selects a new item in the drop-down list our component state has changed and therefore a re-rendering of the employee's component is triggered we can pass in a specific team name as our default value to the use state hook let's pass in team b so when our component is first rendered team b will be the selected item in our drop down list so the next step is to set the value property of the select element to the selected team variable so you can see how react is now able to keep track of the state of our component and render the component appropriately in response to state changes we need to use the set t method to change the state of the selected team variable in order to know when to change the state of the selected team variable our component needs to know as it were when the selected item in the drop down list changes we can use the javascript on change event for this purpose so let's appropriately wire up the onchange event to a method that we'll write in just a bit named handle team selection change let's write the handle team selection change method so we can use the event argument that is passed into our handle team selection change method by default to get the value of the item selected in our drop-down list we can then use the set team method to change the state of the selected team variable this means that when the user changes the selected list item in the drop down list that this action changed the state of our component and our component is then re-rendered let's write codes to log the new selected items value to the console window in our browsers great you can see that we have a few warning messages logged to our console window we'll address these issues as we develop the application i'm in a bit of a bad habit of using class instead of class name when applying css classes to elements please note whenever i forget to use class name and use class ignore me and rather use class name to apply css classes to the elements in your jsx code so we want to add a box shadow around our cards when a user clicks a card on the ui meaning that the user is adding the card representing an employee to the selected team in our drop down list so if the relevant card does not already contain a box shadow around it a box shadow will be added to the relevant card so if the card already has a box shadow surrounding it when the user clicks this card the box shadow will be removed from the relevant card meaning that the employee has been removed from the relevant team selected in the drop down list so basically we want to write code so that whenever a user clicks a card that a box shadow effect is toggled for the relevant card so to do this let's use the on click javascript event and wire up an event handler method to this javascript event named handle employee card click we are going to call the map function on the employees array to return a transformed array where the relevant employee item which in this case is denoted by a card that has just been clicked on the ui within the array is changed in accordance with the team selected in the drop down list so for example if team a is selected in the drop down list the employee item represented by a card that has just been clicked on the ui will change whereby its team name property will be set to the team selected in the drop down list if an employee is already a member of the selected team the card representing the employee will have a box shadow around it when a card with a box shadow around it is clicked the relevant employee items team name property will be set to an empty string the box shadow will be removed from around the relevant card on the ui so the map function traverses the employee items in the employees array the ternary operator checks to see if the employee represented by a card on the ui matches the current evaluated item in the employee's array if a match is found the evaluated employee item's team name property is changed accordingly so basically when a card is clicked if the employee that the card represents is already a member of the team this functionality will cause that employee to be removed from that team if the employee however is not a member of that team that employee will be included within that team once all the employees have been traversed by the map function the newly transformed array is returned and assigned to the const named transformed employees our code is then using the set employees method to change the state of the employee's array this state change then triggers the employee's component to re-render so how do we reflect the change in the state of the employees array on the ui we can add a css class that contains an appropriate box shadow property to the clicked card element or remove the relevant css class if it already contains the relevant css class so we are essentially toggling the css class to create this effect the effect of adding and removing the box shadow from the relevant card so we can achieve this in code by including an appropriate ternary operator that returns the appropriate css code to the appropriate class name property within the relevant div element that represents a card so if the employee's team name property is equal to the team selected in the drop down list ensure that a css class named standout which we'll write in a bit is referenced in the relevant div element else ensure that the standout css class is not referenced in the relevant div element i.e the development that represents a card the card of course represents an employee so let's write the code for the standout css class let's open the app.css file let's add the standout.css class let's include the box shadow property within the standout css class and provide the appropriate box shadow settings excellent so we now want to output status information from the header component whereby when the selected item in the drop-down list changes a count of how many team members exist in the selected team is presented from within the header component to make it easy to communicate state to both the header component and the employee component we can include the state-related code that currently resides within the employees component in the app component which is the parent component of both the employees component and the header component so let's cut the state-related code from within the employee's component like this and appropriately paste this code within the app.jsx file like this let's cut the code that imports the use state hook into the employees component and appropriately paste this code into the app.jsx file now in order for the employees components to be able to effect state and respond to state change we need to pass down the state-related items to the employees component from within the app component we are able to do this in a react application by passing the relevant props to a child component like this prop drilling is an unofficial name for passing props to a child component from a parent component let's take a moment to understand the concept of props in react let's navigate to this url what are props in react we use props in react to pass data from one component to another from a parent component to a child component or components props is just a shorter way of saying properties they are useful when you want the flow of data in your app to be dynamic how to use props without destructuring we are going to use destructuring but let's first understand how to use props without destructuring to use props you have to include the props parameter within your function this is similar to passing arguments into your regular javascript functions here's an example so you can see here the values for the name prop and the tool prop are being passed down to the tool child component within the tool component these prop values can be read through the props object like this so we are passing in our props values from the app component to the employees component in a similar way but we are going to use destructuring to read the relevant props values from within the employees component the next step is to include these props within the function that denotes the employee's component so instead of the props object being passed to our employees component we are destructuring the object into its individual property values so through destructuring we don't have to reference within our employees component the relevant values with props dot preceding the relevant properties destructuring in a javascript expression makes it possible to unpack values from arrays or properties from objects into distinct variables so here we are unpacking values from properties of a javascript object into appropriate distinct variables great we can now use prop drilling to pass in the selected team and count of the number of members of the selected team to the header component we can use javascript destructuring to unpack the relevant props in the relevant object into appropriate variables let's change the header of our header component appropriately let's include code to output the count of team members within the selected team to the browser excellent let's use bootstrap to include appropriate layout code for our header component great let's write code in the app.css file so that text within h1 h2 h3 h4 h5 and p elements are horizontally aligned centrally let's include some basic code in the footer component with some appropriate layout code provided by the relevant bootstrap classes great local storage so every time the state changes for either the employees array or the selected team variable we want to save their values to local storage in react we are able to implement the use effect hook to track state changes for specific variables when a particular state change occurs code passed as a function to the use effect hook can run that appropriately saves our state to local storage so let's see how we can do this in code in the app component where we are importing the use state hook let's also provide code so that the use effect hook is also imported from react we can then pass in an arrow function as an argument to the use effect hook so the first argument denotes the code that we want executed when a certain event occurs for example the state of a variable changes the second argument denotes the event that must occur to trigger the function passed in as the first argument i.e the function that we want executed if however we passed in an empty array like this as the second argument the function passed in as the first argument would only execute when the component first loads in this case we want the function passed in as the first argument to the use effect hook to run when the state of the employees array changes so this is when a user clicks on the card and a team name for an object within the employees array changes ie when its team name property changes to the selected item in the teams drop down list so to do this we can pass in the employee's variable wrapped in square brackets as the second argument then we can appropriately call the local storage dot set item function to save the employee's array to local storage so when the stage changes we are updating the employees array in local storage we can use another use effect hook to save the state changes to the selected team variable to local storage like this great we can then use the localstorage.getitem function to get the value of the selected team saved to local storage rather than the hard-coded value we currently have here that is currently setting the state of the selected team variable by default so by default we are going to be setting the value of the selected team variable from local storage if it exists in local storage if it doesn't exist in local storage it will then be set to the hard-coded value i.e team b so if the relevant value exists in local storage the relevant value in local storage will be passed in to the use state hook and set the selected team variable by default to the appropriate value saved to local storage so we are using what's known as a short circuit evaluation for the javascript expression passed as an argument to the use state hook here what this means is that when javascript evaluates an or expression if the first operand is true javascript will short circuit and not even look at the second operand so we can apply the same logic for the employees array like this so the state of our application will now be persisted to our browser's local storage great one thing i forgot to do is to include an appropriate key attribute within the div element that represents a card that denotes an employee object within a list of employee objects the key attribute helps react identify changes within a list of elements so whenever you have code displaying a list of uniquely identifiable elements it is a good idea to include a key attribute and assign the key attribute to a unique identifier in this case the key is assigned the id of the relevant employee object just to get rid of some of the warning messages i'm getting in the browser console window i'm going to track down where i'm using class instead of class name great routing react router dom the next step is to create functionality so that we can navigate between two of the main components within our react application we have already created one of the main components which is the employees component we'll create the other main component in just a bit which will be named grouped team members so we want to create functionality so that a user through the use of a navigation bar positioned at the top of the web page can navigate between the employees component and the grouped team members component while the header and footer components remain rendered to the screen so we are going to create a nav component that will appear at the top of our page so that the user can speedily navigate between the two main components so let's start by installing the react router dom package let's click the package icon here let's type react-router-dom as search criteria here this is the package we want to install so let's click the relevant plus icon to install the package great and if we open the package.json file we can see that we have installed the appropriate react dash router dash dom package within the app.jsx file let's import the components that we need from the react router dom package let's wrap our header employees and footer component within the router element each component that we want to navigate to will have its own root element so let's create a root element for the employee's component we want only the employees component to render along with the header and footer components when the user first loads the application so the employee's component renders between the header and footer components when the url does not contain any path information then we must include an element property within the relevant root element and set this to our employees element like this then let's include a root element pertaining to the navigation to the grouped team members component let's set its path property to forward slash grouped team members this is the path to a component that we are going to create in just a bit this component can be seen as the other main component of our application the two main components are the employees component and the grouped team members component let's appropriately set the element property to the grouped team members element like this so basically if the browser contains the path to the grouped team members component then the header component the grouped team members component and the footer component will be rendered to the ui the employees component will not be rendered to the ui if no path is provided along with the url of our application i.e no particular path is provided to a specific component then the header component the employees component and the footer component will be rendered to the ui and the grouped team members component will not be rendered to the ui so let's create the grouped team members component with minimal functionality at this point we'll create the appropriate functionality for the grouped team members component once we have written the code for the navigation functionality let's import the grouped team members component into our app component if we type in the path to the grouped team members component in our browser you can see that this component is appropriately rendered to our ui along with the header and footer components great if we remove this path the header employees and footer components are rendered to the screen excellent let's create a file for our nav component named nav.jsx let's write codes to import the link component from within the react router dom package the code for the nav component will basically rely on bootstrap classes for layout and styling purposes so within the first unordered list item let's include a link element that navigates the user to the home page within the second unordered list item let's include a link element that contains the path to the grouped team members component let's import our nav component into the app component let's appropriately include the nav element within our app.jsx file we now have a navigation menu presented to us at the top of our page our navigation functionality is working as expected but we want the navigation links to be displayed next to each other rather than on top of each other like this oh and the problem is that this class should be expand rather than expanded great that looks much better so if the user types in an invalid path we can include a route to handle this to do this we can include a root element below the existing root elements here we can set its path property to a wild card character which will act as a catch all for urls that don't match the paths declared in the root elements above this root element so let's set its element property to a component that we'll create in just a bit named not found so let's create the not found component this component merely outputs a message to the screen stating that the requested page could not be found great the next step is to write the code for the grouped team members component let's open the grouped teammembers.jsx file let's import the use statehook let's include javascript destructuring code to destructure the props that we want passed into our grouped team members component into appropriate individual variables let's go to the app component and write code to pass in the relevant props to the grouped team members component let's go back to the grouped team members.jsx file as stated earlier the use state hook returns a pair of values the current state and a function that updates it the set group data function will be used for changing the state of the grouped employees array let's pass in a call to a function named group team members to the use state hook that will return the default value of the grouped employees array each object in the grouped employees array will contain one property that stores the team name a property that stores the employee data for employees that are part of the relevant team and a property named collapsed the collapsed property will store the state for a list item in the collapsible list that we are going to return from the grouped team members component when a user clicks a team in the collapsible list as it were the collapsed property for the corresponding object will be set to the opposite boolean value currently stored in the relevant collapsed property this state change will cause the component to re-render and the relevant list item will either be in a state of collapsed or expanded we'll write code in a bit to return the appropriate ui markup from this component so that this state change will be appropriately reflected on the ui so the collapsed property facilitates toggle functionality whereby a list item in a list of teams can be collapsed or expanded by clicking on the relevant list item when the list is expanded a list of the relevant teams team members are presented directly below the team list item when an expanded list item is subsequently clicked the relevant list item will be collapsed whereby the relevance team member data will be hidden we are passing a function named group team members to our use state hook here this function will return an array of objects that will be the default state stored in the grouped employees array so let's write the code for the group team members function this function simply returns an array of objects where each object stores a team name a list of team members and a boolean property named collapsed the collapsed property denotes whether a team list item displayed on the ui is in a collapsed or expanded state please note that i would not write code like a code i'm about to write for the group team members function in the real world and the relevant code is only meant to set up relevant grouped data for this example we are going to flagrantly violate the principle of dry don't repeat yourself in this code so the purpose of this function is to transform the list of employee objects stored in the employees array and group the employees into their appropriate teams based on the team name property value for each employee object so let's declare an empty array at the top of our method named teams let's use the javascript filter function to return the team members for team a using the filter function called on the employees array let's create the object that contains the team name for team a the employee objects representing the members of team a and then let's include a property named collapsed let's use a ternary operator to initialize the value of the collapsed property if the selected value in the drop down list is team a then we want this list item to be expanded and display team a's team members so in this case we set the collapsed property to false else the collapsed property is set to true meaning the list item is collapsed and the relevant team members for team a are not displayed on the ui let's write code to add the relevant object to the team's array let's repeat the same logic for the other teams let's write code to return the appropriate ui related code from our component so to do this let's map the data stored within the grouped employees array to the appropriate collapsible list of teams so to handle the event where a user clicks on a team list item let's wire up an on click event within the appropriate div element to a method that we'll create named handle team click let's write the handle team click event handler method in this code we are using the map function to traverse the items in the grouped employees array if team name matches the id of the clicked item then our code knows as it were which team list item was clicked and which items collapsed property value to appropriately change in the array so our code changes the relevant collapsed property to its opposite value of course the collapsed property is a boolean value either true or false this is to create the desired toggle effect for our team list presented on the ui the map function returns the transformed array we can then write code to change the state for the grouped employees array by appropriately calling the set grouped data function we can also call the set team function that has been passed in with the props from the app component to set the selected item in the drop-down list on the employee's component appropriately we are able to change the state for the employees component through the relevant props passed into the grouped team members component so this has facilitated dynamic communication if you like between the grouped team members component and the employees component so appropriate changes made in either of these components the employees component or the grouped team members component will appropriately be reflected in the other component so the collapse functionality is currently not working the reason for this is that i've used a class named collapsed to create the collapse effect in our list this class doesn't exist in our application a class that i meant to reference here is a bootstrap class named collapse when this class is present in the relevant div element a list of team members will not be displayed for the relevant team when the collapse class is not present within the relevant development the list of team members will be displayed directly below the relevant team item let's just quickly fix a small issue here where there is only one member in a team and we want our ui to reflect one team member rather than one team members lastly let's neaten up our code a bit by appropriately abstracting certain functionality into their own components so for example we can abstract this code within the employees component that renders the drop-down list to the ui into its own component so let's do this please feel free to reference the relevant code at this location on github if you get stuck at this point let's abstract the code that traverses the employees array into a component named team members a component named team member card is called from within the team members component we can include the code that resides within the employees component that renders the cards to the ui within the team member card component so let's create a component named team member card that renders each card appropriately to the ui the code is now much neater great let's include a media query within our app.css file so that on small screen sizes each card is presented in a new line so by doing this we are making our spa application responsive excellent note that i've created two versions of this application that can be found on github the version that we created in this video can be found at this location as an added bonus i created another version of our application on github that can be found at this location in this version of the application i have implemented code for abstracting the management for passing data between components through the use of context let's navigate to this url and read a bit about context context provides a way to pass data through the component tree without having to pass props down manually at every level so by using context we can avoid prop drilling in a typical react application data is passed top down parent to child via props but such usage can become cumbersome for certain types of props eg local preferences ui theme that are required by many components within our application context provides a way to share values like these between components without having to explicitly pass props through every level of the tree the application that we have created is small and fairly basic when an application grows it may be better to use context so that the code used to share values between components is neater and easier to maintain please check out this version of the code on github to see how i have implemented context for the purpose of sharing values between components without using prop drilling with react you can break down an interface into reusable components that allow you to build dynamic user interfaces react can be described as a mature javascript framework and it has an enormous community supporting it the performance that react provides makes it an excellent choice for the implementation of front-end user interactive functionality i highly recommend learning this technology now that you've learned the basics of react with gavin it's time for you to apply that knowledge to a more complex application john smilga is your instructor for this next section hey what's up it's john from youtube channel codingaddict and welcome to our next react project the meals application and before i showcase the app let's quickly discuss the main objectives of the project and essentially there are two of them first in this project we'll learn how to fetch data from external api and as a signal during the project we'll utilize the meal db api as our external data resource and our second objective is to get familiar with app level state and more specifically context api since it's something you simply can't avoid when building more complex applications if you want to take the project for test drive just navigate to this url mealsapplication.johnsmailga.repple.co again the url is dub dub dub meals application dot johns milga dot reply dot co and as far as the functionality using this application user can search for the recipes so when the application loads we display some default recipes and if the user is interested in the cooking instructions he or she can click on recipe and here we display the image the title cooking instructions as well as original resource effectively this is where the original recipe is coming from and also we can close the model now user also has a option to search for recipes based on a search term so for example if i go here and type a now i'm going to get all the recipes where in the title there's a letter a now also user can get some random ones if he or she clicks on the surprise me notice now we're getting the random recipes and also there's an option to add recipe to the favorites so if let's say i like this recipe i can add it to the favorite now we also have an option to remove from the favorites and we can also take a look at the favorite recipe again in the model now the favorite recipes will be persisted in the local storage and therefore even if you leave the application and come back later you'll still have the recipes that you saved in the favorites so it's not just going to be the local state but also will implement the local storage for this project i also created a readme file and in there you'll find useful external resources code snippets and all the steps we're going to take to build the application i like such approach since it saves you time on taking notes essentially all the important stuff is already documented and more importantly it allows you to work on a project independently once i'm done explaining the step if you feel like working on it independently just pause the video and try to solve the challenge on your own and resume it once you're ready to see my solution lastly i will share the url basically where you can find the source code with the readme file in the following videos just remember that you can always find both urls for the complete app which we covered in the last video and for the source code in the video description below okay and we're going to start our journey by creating a new project in the replit so assuming that you've logged in or registered go to your dashboard and look for create button in there look for react template and at least i'm gonna go with default name but of course you can come up with whatever name you want for your application and once all the dependencies have been installed just click on run so we can see our project in the browser and then at the very end of the video i'll just change the title in the index.html and basically this is what we see in the browser tab so since i have logged in let me just navigate here to a dashboard and like i said we're looking for create if you want to see all your projects they're going to be down here so let's go for create we're looking for a react template and i'm going to go with this default name that they offer and now we want to go with create repel we'll just have to wait a little bit for the dependencies to be installed and once everything is ready to go we just want to go with the run so effectively this is going to open up our application in the browser tab here on the right hand side and once i can see my application in action let me just showcase that all the way in left hand side these are going to be our files then in the middle we'll have our code and in my case i'm going to keep it between 200 zoomed in and 250. so hopefully that way you can see clearly my code and i'll also change the size from time to time of the browser tab just so i have a bit more real estate here in the middle all the way in the bottom we have the console which for the most part we're not going to use and what's really cool that for our little browser window we also have the devtools so if you click on these ones notice here we can also see all the errors warnings and of course our console log and rest of the stuff now we also have this cool option of opening this one up in the new browser tab and as a result we get a bigger canvas so from time to time yes i'll switch actually from this small one to a bigger one because it's going to be easier to showcase the devtools and all that cool stuff and at the very end of the video i just want to change here what we see in the page so let me just go here with meals and app and i'll do the same thing in the index.html so let me navigate to index.html here where we have the title we can change the name so let's go with meals app let me save it and of course we can see the result in both places in the small browser window as well as the big one okay and now let's grab some assets from the complete project so first what i want you to do is navigate to this url and again the url is following we're looking for replic.com at johnsmilga and meals application now here of course it adds that hashtag readme because that's the file where i'm at but the main url is again replic.com johnsmilga meals application i want you to navigate there and more specifically navigate to app.css and then we'll talk about what we want to get from there as well as why i suggest copying readme so first let me just showcase the url so copy and paste everything that i have right now now just remove that readme now if you have a different view of the application again it doesn't change the files that you're looking for so navigate to the source folder you're looking for app css and at this point you have two options if you don't want to type css together just take the whole thing so just copy it and set it up in your project now if you do want to type the css and i'll sign up yes i'll make the css video separate so that way if you don't want to type the css together you can just skip it or if you do want to build it together then just grab everything up to the end of global styles which is going to be my case of course since we'll type the css together again this is a somewhat of a hot button topic because some people prefer typing css some don't so in this case you have an option if you want to type out the css together then just grab everything up to the end of global styles if you don't want to type the css then just take the whole thing hopefully i made myself clear and like i said in my case i'm going to take everything up to the global style since of course i will write the css for the upcoming components now i'll cover the global styles in a little bit more detail in one of the upcoming videos for now just take the css you want to get from this file navigate back to your application look for source look for app.css remove all the code that you have right now save it and you should see different result on the screen now when it comes to readme i just think that it's better if you have those steps in your application now you don't have to copy the contents i mean you don't even have to follow along as far as these steps but i think it makes more sense if you want to work on the project independently and therefore in my case i'm just going to take all the code that again i have in the complete project readme and i'll just navigate back to the project that we just started building again i'll remove all the code that is currently there and copy and paste and successfully we have acquired all the assets that we needed from the complete application so at this point i can actually close it and from now on of course we'll be doing all of our work in the application we just created and when it comes to global styles essentially you'll just find some settings for typography a reset css variables for example for colors as well as the bore radiuses box shadows and then just some general styles including some classes that i use somewhat often for example button and as i know this is something that i use not only in react projects but pretty much in every project that i make because in the long run it saves me a bunch of time since i have some preset values and that way i don't have to reinvent the wheel each and every time awesome we're pretty much done with the general info so now let's start coding and the first thing that i want to do is to set up a structure for our project and in order to do that i want you to create a components folder in the source and there are four files effectively these are going to be our components in microsoft i'm going to go with favorites meals modal and search all of them will have that jsx extension and in there we want to create a component and in my case i'll set it up as a arrow function now i want you to set up a basic return in my case i'm going to go with component name but of course you can type whatever you want in the return as long as we can see something on the screen now my personal favorite is shake and bake but of course you can for example go with heading one and dude where is my car as long as you can see something on the screen we are good to go now we do need to remember to export this as default and then in the app js we'll import all of them and set them up one by one so effectively the component is going to look something like this for example search one again i have the function i have some kind of basic return and i'm exporting as a default then we want to import all of them in app.js and set up the following structure so notice these are all the imports for our components and then inside of the main we want to go with search favorite meals and model and if you can see all the returns on the screen you're good to go and last thing that i will do at least in my case is to comment out search favorites and model why well because we'll start working in the meals and even though i do want to see that the component has been set up correctly so essentially in the beginning i do want to see some kind of return i just think it's going to be easier at least for me as i'm developing and showcasing stuff just to have the component that we're actually working in so this is how i'm going to set up the structure for the application however i'm going to do that in the following video so if you want to work on this independently then once this video ends just try to set it up yourself and if you want to see my solution i'll cover it in next video okay so let's get cracking first we need to create a components folder so let's go with add folder in the source and i'm going to go with components now there we want to add some files yep that's correct and of course we can see the list of files we need to create so one by one let's just set them up i think i'm going to set up the files first and then i'll set up one return copy and paste and just change some values so first let me add those files we're looking for meals jsx then we also want to set up a modals jsx and then lastly we have the search one so let's go with add file and we're looking for the search jsx so let's start i guess with the favorites where we want to go with our arrow function so const and in my case i'm going to pretty much name it same as the file so favorites here it's going to be my arrow function and as far as return i'm just going to go with heading 1 and i'll write favorites and then the component component and like i said we want to export that as default so export default and i think i actually want to get it in the app just right away so before i copy and paste anything let me just go to app just and we want to import that from components so favorites from and then we want to go with components and more specifically favorites file and then where we have the main one why don't we change this around and let's just say favorites so that's our component and if everything is correct this is what we should see on the screen and since i can see that that's the case now let me just go here and i'll copy these values so i'm looking for a meals one i'll copy and paste then i'll select all the instances with the command d at least that's the shortcut on a mac and then we'll change it around two meals we want to do the same thing here in the modal and copy and paste i'll just write modal and then the last one is going to be a search one so again let's select everything all the instances are favorites and let's go with search let's save it then we want to navigate back to app we want to copy and paste and we'll just set up a few cursors here so the second one is going to be meals then we'll be looking for the model i believe so let me type here model actually messed it up here a little bit so let me go with the forward slash and then lastly we also have the search one i believe so let me remove all of them and then let's go with search now as far as the structure we'll start with search favorites meals and model so let's go here search then we'll have the meals and also have the model so model over here and if you can see four heading ones displayed on the screen we're in good shape basically we're moving in the right direction and once everything is good to go then one by one i'll just comment them out like i said it's easier a way for me to showcase which component we're actually working in otherwise you might be confused by all of the heading ones that we can see on the screen now the way we can set up a comment in the hsx is actually in a following way so let me showcase that notice so we go with curly's and then inside of the curlies we go with forward slash and then star and then star and forward slash and then whatever we place here is going to be commented out again eventually we'll use those components but for now what i'm going to do is back in the app just like i said you want to set up the curlys here then we want to go with forward slash and then star then star forward slash and i'll copy and paste right away and i'll set up one for search one for favorites and one for model because we'll start working in the meal so one by one let's place them there so you cannot see the search anymore you cannot see the favorites and also you cannot see the model and now let me move this sucker down we have meals ready to go so now we can move on to our next step okay and now let's talk about the app level state and essentially it's a decision we need to make of how we're going to handle the props in our application because one thing we need to keep in mind that in react we can only pass the props down so for example in our application we're going to have favorite meals and then once we click on a meal we actually open up a modal so there's going to be a communication between the favorites component and the modal component and as you can see it's not like we can just directly pass from one to another one effectively we can either set up all the functionality here in the app.js since that's the root component again we can only pass the props down we can go with context api something that we're actually going to do and therefore i'm not going to go into more detail since we'll cover all of that in the upcoming videos and also we can go with third-party state management library for example redux or redux toolkit and then of course there's million more now honestly in this case in this particular application we actually can go with app.js approach since there's not that many levels that we need to pass however again we need to keep in mind that all the logic is going to be here in the app.js since this is a root component and then from the app we pass to a separate component now the problem is going to start as your app grows more complex and if you have more nested structure for example you have more components inside of these components then effectively becomes a pain and it's not an official name for that but it's referenced as a prop drilling where basically you pass the props down to one component then it has some nested components so we keep passing down and down and down and one of the solutions for that is using context api now once you get to really complex apps then it makes sense to use redux redux toolkit my personal favorite at the moment and some other choices that are out there so in this application i didn't see the point of actually using redux or redux toolkit and therefore the choice was really between the app.js and context api and even though in this scenario we can set up all the logic here in app.js i decided that this is going to be an awesome introduction to the context api all right and now let's talk about the context api and before we go any further let me just mention two things first if you don't find my explanations good enough i can always suggest this article by free code camp where they cover context api in a great detail now the second thing that i want to mention even though yes context api is an awesome approach still keep in mind that it has its limitations yes it's good enough for this project and it's way better than just passing down props from one component to the next one let's say seven levels deep however once your app grows and becomes really complex essentially you'll hit two roadblocks first there's less structure than for example tools like redux and redux toolkit and that becomes especially important if there's a team working on a project and the second roadblock you'll most likely hit is the fact that it's somewhat clunky to communicate between multiple contexts so when it comes to really complex application most likely you'll not only have one context api you'll have multiple and at least in my experience it's way easier to communicate between these functionalities when using the third party state management library like i keep saying redux toolkit because that at the moment is my favorite now as far as the setup for the context api again effectively it's a way for us to have all our logic in one place and instead of prop drilling where we pass the props from one component to the next one again let's say seven levels deep we can set up all the logic in one place and then that specific component can just cherry pick what data is necessary and if at the moment you're somewhat fuzzy on that don't worry once we set up the actual example it's going to become clear so first we want to create a context jsx file somewhere in our root now technically you can create the components and all that but i always prefer setting it up in the root now when i say root of course i'm talking about the source then we want to import react and use context something we're going to use a little bit later from react and we want to come up with a variable name now i always like to go with app context or some meaningful name that references the context that i'm creating but again shaken bake is also a good choice then we want to go with react dot and create context so we have this method that creates the context and once we invoke create context effectively we get back two things we get back the provider and we get back the consumer now let's not worry about the consumer right now let's just worry about how we can pass the data down and we do that with this component of provider now notice here though how we will set up a brand new component and i'll talk about the children once we actually set this one up but in here in the return we go with that provider so this is what we're getting back from that create context and then in the value prop whatever we'll pass in at the moment is just a low we can access pretty much anywhere in our application and then the last thing that we need to do as far as the provider we need to export it and we'll also export this app context and this is going to make sense a little bit later so in here i'm talking about the main item that we're getting back from create context and then we want to wrap our entire application in the app provider so the component that we're creating over here so we want to import that since we're exporting from the context and we want to wrap our application now while we're still in the index.js i want to mention that because of react strict mode while in development you'll notice multiple logs so if you're wondering hey why while i'm developing i'm getting quite a few console logs it's because of the react strict mode that's just basically a setup in development and once i've covered the general concept now let me set up the context api in our application okay so now let's set up the context in our application like i said i prefer setting up in the source so let me create a new file i'm going to go with context js and here we want to look for react and we also want to right away get huge context now we'll set this one up later we use contextual but we might as well import it right now then we want to go with the name in my case that is going to be the app context and that one is equal to react and then the method name is create context we invoke it and again we get back those two components now since i want to return provider from the component that i'm going to be wrapping the application i need to first create that component naming is up to you in my case i'm going to go with provider again this is a separate component that will wrap our application and from this component we're going to return app context dot provider very important distinction so in here we'll access children and i'll showcase that once we actually wrap the application because it's going to be easier to understand that way so let me go with return here return and we want to go with app dot context dot and then we're looking for provider like i said we get back two things the consumer and provider but with the arrival of use context we actually don't need to export it from the context.js so that's why we just need provider and then it has the value prop whatever we'll set here in the beginning is just going to be string but eventually it's going to be more complex data structure that one will be passed down to all the components and as a result we won't need to do that prop drilling now we do want to display the children against something i'm going to cover in a sec once we can actually access everything and now let's export from this file so for now we want to export the app context as well as the app provider both of them are named exports as you can see so let's save it if nothing breaks we're in good shape now let's navigate to index jsx we want to grab the provider so import app provider now that one is coming from and then of course we're looking for the context and then we want to go where we have our application and we want to basically wrap it in the app provider like so so let's wrap it again if everything still works if there are no issues then we are in good shape and it looks like i have an error and actually it's because of the name the extension should be here js6 my bad once i fix the extension everything should work as expected let me restart and yep i can see the meals component now the reason why we want to grab the children pop and set it up here in return because this is our application so essentially in react children is a special prop and that represents pretty much whatever we have inside of the component so in our case what we have inside of the component is the app one so in the app provider we have app and in our function that is represented with this children again this is a special prop that's why you go here with curly braces we structure it we grab the children and we pass it here if you won't do that basically you won't see your application notice how nothing is displayed so that's why it's important for us to grab the special children prop and then pass it down because this is our entire application and once we have set up the provider now let's see how we can access the data in any of our components beautiful we were able to set up the provider so now let's see how we can consume the data now before we proceed i actually want to make some changes in the workspace so first i noticed since i used that default name i actually don't see the working application in the dashboard essentially it's under unnamed and i've said that i'll actually change that so let me navigate here and in order to do that i just need to click on this icon and then let me go with meals meals app and then let me add temp or you know what i'll start with temp i'll go temp meals app so that way i know that this is just temporary while i'm recording okay so that's done and then the second thing that i want to change essentially is the workspace where it's nice to have that browser window but the more code we're going to write it's actually more important for me that you can see clearly all the code and readme that i'm providing and that's why i'll actually open a new one the browser one and that's the one that i'm going to use to display the results so in here we can simply close the webview then we'll have the console not technically you don't even have to close i believe the webview you can just simply push it to the side and finally i'll zoom in and hopefully it's going to be easier to see the actual code now as far as the consuming data what do we need to do well once we have set up the provider we can go to any of our components and again the magic here is following that it's not just these components in the components folder it can be any components that are sitting inside of these components and that's truly powerful because again we don't have to pass those props seven levels down and in order to consume that data we need to go with used context so we need to go to any of the components where we want to consume the data in our case it's going to be meals since that's the only one that's rendered because i don't want to get use context hook from react we want to get the app context from the context so remember when we're setting up the context this is what we're exporting correct we're exporting the app provider so the component of that wraps and from there we return the app context provider and we also exported the entire context so now in the meals we want to access that entire context so let me go back to readme and not only that but we want to invoke the used context and pass in the app context so import both things passing app context into use context and then we'll get back what will get back that value so whatever we place in the value prop in the provider and then for time being i'll just cancel log it and we should see the hello in the browser devtools so let's navigate to the meals here then we want to go on the top and import both things so import then use context that is coming from the react and then we also want to get the app context so import app context and we want to go with from and of course we're looking for the context so this is going to be right outside of the directory the components one and then let's grab the used context invoke it and pass in the app context so const this is going to be the result we're getting back so that is equal to use context and we pass in the app context and now let's simply log and i know it's probably not a big deal to see the hello but once i show you something you'll see why this is so powerful so let me navigate to the browser i'm going to open up the devtools and that is also something why i want to use the big browser window because it's going to be easier to see actually our console so let me refresh and yep now we have the hello and now you're probably wondering okay what's the big deal well the big deal is that we can turn hello into something more meaningful so if i navigate back to the context it's a prop the value one and at the moment i'm just passing the string however we can change this around and we can say that it's going to be an object so first we need to set up the curly braces effectively that means okay we're going back to the javascript line so either we can set up some kind of expression here for example variable or i can just simply pass in the object and i can go with name and then john and also let's add a roll and we'll set it equal to a student let's say that and now in the meals this is what we should see so let me again refresh and we have name john and then a role student and now we can put two and two together if we can pass in the object that means that instead of the app provider we can set a bunch of functionality which effectively is something we're going to do so we'll set up some functions then we'll pass down we'll set up some state variables that will pass down and effectively any of the components in our application will be able to access it just by grabbing use context as well as the app context and again i know i've said this 10 million times already but this is extremely extremely powerful concept because it saves us a lot of mental energy because we can set up the code in one place and then import it in any of our components all right and before we start talking about the data fetching and react now let me also show you how we can save on one import in the components that are going to consume our data so if you remember the previous video we needed to import two things the use context and app context in the component and then passing the app context in the use context what also we can do is set up a custom hook now let me just make it very clear the previous example is not incorrect there's just a better way where we can have one line of code and in order to set up we need to create a custom hook which is also something that we can do we just need to make sure that the name of the hook starts with use now the name is really up to you in my case i'm going to go with use global context and as you can see we're setting that up in the context.js and we're exporting this right away so we go to export const then whatever is the name of the hook and now notice the functionality we return from this hook from this function what we return use context we invoke it and we pass it in the app context now where did we see that one before over here so we grab both of those things in the context.jsx and remember that both of them are already present we imported the use context and we set up the app context in the context.js and then we just go with use context app context and we're returning from that hook now as a result we can import the custom hook instead in any of our components and then invoke it again the setup is almost the same we're just saving one line of code which in the long run if you have let's say 100 components makes a lot of sense so let's try this one out i'm gonna navigate back to the context one let's scroll up and it doesn't really matter where you set it up but i always prefer doing that right before the export here and now let's go with that custom hook again remember we already imported the used context from react so that is not a custom hook that's the one that comes with react which allows us to access the context and let's go with export const and then use global context and say not of course you can pass it here as well it's just i prefer this way and then it's going to be a function and then from this function what we simply want to do is go with return use context and then pass in the app context now let's try it out in the meals so let me navigate back and then instead of these two suckers we'll remove the first one and we'll change what we're getting from the context we'll simply go use global online context and now let's invoke so use global context context let's invoke that and again the result in the devtools should be exactly the same so i'm going to navigate back again i do need to refresh and check it out we still have the object with the properties of name and raw and with this in place we have successfully set up the structure to consume our data from the context.js and what that means is that we'll just have to set up the entire logic in the context.js and then each and every time we want to get the data again we're talking about the state variables or functions that we want to invoke we'll just use use global context and we'll cherry pick which info we want to get from the context jsx which again is extremely extremely powerful concept because it saves us time and mental energy in the long run and now let's talk about another extremely important topic and that is data fetching in react and let's start with the most pressing questions first where and how so essentially we can fetch data in any of our components however in our case since we'll pass this down we want to do that in the context but yes if you want to set up some data fetching in search component you can do it the same way as i'm about to show you in the context.js and the same goes for any component you create so hopefully that is clear now how we fetch data in react well we want to use use effect hook because it allows us to control when we're actually going to fetch data so if you remember from the previous videos use effect is a hook that runs after every render by default so by default it runs after every render however it also has this cool feature called the pen and zero which we pass right after the callback function so when it comes to use effect effectively we invoke the hook we pass in the callback function and then this callback function whatever code is in there is going to be invoked after every render again that is by default if we pass this dependency array and if we leave it empty then it's just going to run that callback function when the component mounts or in the other words when the component loads now we do need to understand that when it comes to context essentially it's only going to load once because it's in the root of our application take a look at the index one notice so we have this app provider that's the one that we're exporting from the context and therefore this is going to load once we open up the application again i'm not talking about the re-renders that possibly might happen after that i'm just talking about that initial load and that's the one that we actually get from this empty dependency array so when we set up the empty dependency array in the use effect essentially that means it's only going to run when that component in our case app provider loads or mounts now we can also pass here some values and then it's going to run every time the value changes but let's not worry about it i just want to make it very clear that when it comes to data fetching we for sure need to pass in that dependency array and i'll show you in a few videos what essentially is going to be result if we don't do that let's not worry about it right now and you can start simply by setting up some kind of console log in there so go to context.jsx import use effect then invoke it pass in the callback function set up the empty dependency all right and then in my case i'm just going to say aph data here now once that is done then i'll cover one more gotcha that we need to remember about this callback function and then i'll lay out the steps that i'm about to take in next video so first let me navigate to context.jsx i want to get the use effect and i want to actually invoke it as well so in here we want to go with use effect so that's the hook that's coming from react then we want to invoke it right away so let's say use effect let's set up the callback function like i said empty dependency array and then in here let's just say console log and fetch data here let's save that and now let me navigate to the browser and check it out now of course i have the console log here now what is the gotcha that i was referencing before well it's following when it comes to this callback function it cannot return a promise so you cannot turn this into a sync function because if you remember by default the moment you set up a function to be async it returns a promise and react is not okay with that so we cannot turn this into a sync function now why am i saying that well because when it comes to fetching data effectively we have two approaches we can use dot then or we can use async await so when it comes to that then if that's the approach that you prefer you can easily set up the code right here instead of the callback function you can for example go with fetch api so you go to fetch let me write here fetch then the url then we go here with that then and then you know the rest so you can definitely do it here now if you want to go with async await essentially you have two options you can set up the function here inside of this callback function and then invoke it or you can set up the function outside and then invoke it again the reason why we need to do that is because we cannot turn this one into a sync function and then call await so we need to set up a separate function so hopefully we are clear on this and now let me show you the challenge that i have for you so now that we know that we'll use used effect to fetch our data i want you to try fetch data now you can use fetch api or axios that is really up to you that is irrelevant first i'll show you the fetch api approach since that is built in and then i'll switch to axios and this is another hot button issue because every time in tutorial i use fetch api i get comments why i'm not using axios and then once i switch the axios i get people asking why we're not using fetch api look just pick the one that you use and you'll be good to go there are not going to be that many differences so pick either fetch api or axios just remember that with axios we do need to install it and this is something that of course i'm going to do in a few videos and you can use any url that's why i have here from any url in the use effect callback function so again you just need to remember that if you're using that then it's one approach if you're using async await then it's going to be another approach and for time being just log the result just log it you don't have to do anything complex just log the result try to set it up and in the following video i'll show you my solution and before we continue let me just mention that in this video i'll use fetch api and if you're not familiar with fetch api or you just need to jog your memory in the readme i shared a awesome article by free code camp and basically i'm going to use the random user api and the way it works this is the url and then essentially just returns a random user again the structure here is not particularly important since that's not what we're going to use in project i just ended up using this url because it's pretty short and straightforward and then the way i set up the logic like i said in the use effect i set up the fetch data function because again i know i've said this before already but we cannot turn the callback function into h sync since i want to use a weight that's why i created a sync function so fetch data a sync function and then since we're working with asynchronous requests i just set up the try catch as well just keep in mind that when it comes to fetch api this doesn't really worry about the errors unless they're network errors and that's one of the differences between the fetch api and axios which effectively we're going to use in the following videos so in here i went with response await fetch then passing the url and then we need to turn this into a json so i waited for response.json got back to data and then logged in and also just in case logged the error and right below where i set up the function i invoked it as well and once i set up the function in the app provider also showcase how we can move it outside of the callback function because essentially that is going to be our approach in the upcoming videos so now let me navigate to the context and then for now i just have this console log here let me remove it let's go with const fetch data is equal to async that's our function now fetch api is built into the browser so we don't need to import anything we want to go with try and catch let's come up with const response is equal to a weight fetch now let me grab the url and then let me set it up as a string of course now we have a weight okay that's beautiful then const data is equal to await and then response json let's invoke it again and now let's just log it so console console and then log and then let's pass in the data now let's do the same thing in the error we just want to change what we're logging over here and we have the function that's awesome but of course for anything to work we also need to invoke it so we go with fetch data here now again let me navigate to the browser and check it out and here i have this giant object again we're not really concerned what we're getting back the idea is just to showcase how we fetch data so that's the first step after that we'll set up the state variables and all that and now let me also showcase how we can move the functionality outside of the callback function so this is definitely one approach that you can use but in our case we're actually going to set it up outside and then we'll invoke it inside of the use effect effectively i just prefer this approach better now there are times when you want to do that and use effect but again in this case it doesn't really matter so let me take this outside so again i'm talking about the function the fetch data function um now let's see whether everything still works yep i still get back the results so we are in good shape okay and once we're familiar how we can fetch data react now let's take a look at the api we're going to use for this project and before i show you the documentation as well as the urls i actually have a challenge for you so either you can follow this link or just go to your search engine and type mealsdb regardless you will hit this link and then get familiar with docs so try to understand on your own what the api offers and more importantly get two urls get the one that allows us to search meal by name as well as the random one now here's the hint in the docs this part is missing so either you'll have to add it manually and you'll see why in a second or just take the url place it in the browser and then copy it so again you have two approaches i usually prefer the second one i just find it faster than typing and then in the context jsx set up two variables now in my case i'm going to call them all meals url and random meal url and assign the corresponding values so as you can see in here we're searching meals by name and this is going to be our all meals url at least in my case and then the random meal url is going to have this value again this is the challenge go to docs get the urls get familiar with documentation and in next video we'll do it together okay and as far as the api we'll use this one so i believe the official name is the meal db and effectively we just want to navigate to the documentation and as you can see they just provide a bunch of urls so some of them you need to be a patron and some of them are for free so these are the two that we're going to use we're going to go with search meal by name and we also use this one look up full meal or no sorry look up a single random meal got carried away over here and just to showcase what we're getting back let me just copy this one let me go to the browser and check it out so effectively we'll get back the object in there there's going to be an array by the name of meals and then each meal is essentially a object itself with bunch of properties now of course this is already a full name if let's say we change this around and just go with a we'll get more items so now as you can see we have more meals that are again objects in that array and then we've got an id we've got a image and as you can see a bunch of other stuff as well so that is as far as the search meals by the name now another option that we have is look up a single random meal and what's really cool that actually they send back that one random meal but it's still structured as an array and for somebody who built the application that is actually very nifty because you don't have to change anything as far as the logic on the front end so if i copy and paste notice i still get back that one meal correct but the structure is still the same and if you have been setting up applications with api and front end you know that it makes things easier if you don't have to restructure your application based on the urls coming from the same api now again there's multiple variations of course there's cases where it's not possible to always have pretty much the same structure but in this case this is super nifty so now we just want to take those two urls and set it up in the context so now let me navigate back to our project and then i'm gonna go to context.js i'll take a look um most likely i'll just do it above here where we have the context and then let's come up with those two variables so my case is going to be all meals url and then the value will be this one over here so that's the one where we'll pass in the search value and for now i'll just leave it as a of course eventually it's going to be dynamic and the second one will be that random one so let me navigate here and then again let's come up with that variable name in my case it's going to be random meal and then url and then let's pass in the value all right add up next we want to refactor our fetch data function where first we want to switch to the axios library and as i know if you're not familiar with the library or you just need to jog your memory here's an awesome article by free code camp and also we want to switch the url to the get meals by name one remember it was stored in the url variable and the steps are following we want to install axios so we can do it over here where we have the packages then we want to import it in the context.jsx and as far as refactoring i'm going to change the name of the function i will switch from fetch api to axios then i'll add the url parameter because we will invoke the same function multiple times with a different url eventually so we might as well do that right now and i'll pass in the all meals url so we'll switch to all meals url and lastly just log the response if you get stuck feel free to take a peek at my solution below so let's refactor our fetch data so the first step is going to be installing axios i'm going to navigate to this tab and then let's type the name of the library of course it is axios we want to install and as far as the brief intro axios effectively is a http library that makes our life easier especially as your project grows and you have more complex requests and we want to import that in the context.jsx and then i'll show you how basically our factor the application so let's start here by navigating to the context jsx and then we want to import the axios import axios from and then we're looking for the axios library and then as far as refactor let's take a look at the readme essentially we want to switch from the fetch api to the axios and i also want to change right away the name so instead of fetch data i'm going to go with fetch meals i'll pass in the url so instead of hard coding the url i'll pass it as a parameter and again the reason for that is because we'll invoke the fetch meals multiple times and based on the conditional pass in the url and in here we just go with a weight and axios so we don't need to turn this into a json and we just log the response now axios does have a kind of more complex response so we'll actually have to pull out the data but let's not worry about it right now we want to invoke fetch meals and then we want to actually pass in the all meals url now of course in your readme it's going to be already there and once we do that we should be in good shape so let's try this out in the context i already have the axios okay so that is done now let me find my fetch data i'm going to call this fetch meals then i'll pass in the url that's going to be name of my parameter and instead of console logging the data we'll take a look at the response and then instead of fetch we're going to go with axios and here we'll pass in the url so instead of hard coding this like we did previously we'll pass in the url then let's keep on moving and now we want to pass in the all meals url let's save it and let's take a look at the browser so in here there's a complaint that import from axios blah blah let's see whether refresh is going to help and nope that's weird maybe i was just too busy talking and i actually didn't install the library so let me double check i have dev dependencies okay and then yeah i have nothing here so let me go back to the installer and let me look for axios one more time that's what happens when you talk too much so let me install the package and now everything should work as expected so now let's take a look at the browser let me refresh and then if everything is correct and of course fetch data is not defined because i forgot to change the name my bad so let me navigate back to my context and then here of course i change the name so it should be fetch meals instead of fetch data let me save for the third time yep and now everything works now when it comes to actuators like i said the response is more complex so in here we actually get the config we've got data as you can see it's a giant object now what we're interested is this data property so if we are successful then data that we're getting back from the api from the server is going to be located in the data property now like we covered already before the way the api sends back the data there's a meals array so that doesn't change it's just going to be located in the data property and at this point we have multiple options either we can just destructure it or we can go with response and then data now keep in mind though the value is in the meals so still have to access that property but i'm just showing multiple ways how we can access it now i always actually prefer the the structure route where i just type data and now i directly access the data again let me say one more time and now we should see again that meals array which is an array off object and lastly let me just showcase how we can access error in the axiorys so i'm going to go back to my fetch meals we're looking for error object and more specifically we're looking for error dot response so that's where we can access the error and in order to showcase that i'm just going to go to the all meals one i'm just gonna type some gibberish here and then if you take a look at the console notice you'll have the error and in this case you can take a look at the error response as well so that should do it for the axios and now we can proceed to the next step okay and up next let's set up the meals state variable and just render something in the meals component now before i continue let me just mention that if you did also change the value in the url in the previous video just to see the error please make sure that it's back to the original url otherwise the functionality is not going to work as far as the setup we want to go with import use statehook in the context then we want to set up the state variable at least in my case i'm going to go with meals and remember that it returns an array with two values the meals value and the function that controls that and then we wanna set the state variable from our fetch meals function remember we're getting the meals from the api and remember the structure of the response and we want to use set meals to set our state variable equal to that data then we want to pass the meals down to our entire application and remember we do that in the value prop and we want to structure the meals in the meals component lastly we want to iterate over the meals log each meal and then render something on screen again it doesn't really matter what you render as long as we can see that we're getting the data we are correctly iterating over and we have something on screen we're in good shape as always if you get stuck feel free to peek at my solution below all right and as far as my solution i'll start by importing use state in my context jsx so let me add this over here then i'll set up that state variable by the name of meals and remember we get back the array we write away the structure this is going to be the value and this is the function that controls that value initially the value will be empty array and then in the fetch meals remember the array is actually in the meals property so there's a data object in there we have the meals property and in there we have the array so we run set meals this is going to set our meals state variable and we want to pass it down to the entire application that's why in the value instead of the name and whatever it was the role i believe we'll pass down the meals and then in the meals component we'll destructure it remember the setup is already in place we just need to change what we're looking for since we're passing down the meals instead of the name and the roll now of course we're looking for that property in the emails component and then lastly let's set up the return where i'm going to go with section now technically you don't have to add section we'll worry about the css in the following videos but i'll write away gold section since that's what i'm going to use but you can also use div of course then we'll iterate over the array and then for every item in my case i'm going to call it single meal that's going to be that object i want to log it i want to see the proper issue that we get back since we'll have to destructure them and at least in my case i'm going to return a heading 4. so if everything is correct i should get i believe 25 heading 4s on the screen so let's try this out first i want to go to context jsx i will look for use state then i'll set up that state variable so meals and then set meals so that's the function of course that controls it use state and i'll start with empty array because remember we'll be iterating over and initially if you'll set it equal to null then the functionality is not going to work because it takes time to fetch those meals and i'll talk about the loading and also if we get back nothing from the api what to do then so we'll cover those conditions but just remember that yes we do need to start with empty array then let's use the set meals and then pass in data and then meals that's where the emails are located and now i believe we can just remove the console log then instead of these two suckers we want to pass down the state variable let's save it and then lastly in the meals component first i want to grab it so instead of this context i'm going to destructure meals and now let's iterate over where first we want to go with section then inside of the section we'll iterate over the list so let's go with meals dot map and we pass in the callback function and i'll reference each and every item there the object as a single meal and what i'm returning from this map function well for now i'm just going to go with heading 4 and single meal and then let's also log it since we'll use those values in the following lecture so let's go with single meal let's save it and like i said if everything is correct i should see a bunch of single meals on the screen and we do and also notice over here yes there are some warnings about the key prop and all that we'll worry about it in a second for now i just want to showcase that these are the values that we get back for every object and they should match what they should match this correct so this is also what we can see in the browser and if you have the same result now we can move on to the next step okay up next let's display a nice card for every meal that we have in the array and the way it's going to look like so i'll add right away classes for css but like i said i'll do the styling in a separate video so if you already copied these styles you're good to go if you didn't then don't worry if it looks somewhat ugly in the beginning we'll worry about the css in the following videos so first i want to grab the properties from the single meal now how do i know that those properties are there well because we logged them in the last video correct and we can also of course see them in the browser if we just provide the url and the properties that i'm interested are id meal which is going to be the meal id then i also want to get the title and notice how i'll pull out the property but i'll right away give it an alias just so it's easier for me to work with the value now do you have to know of course you can still use the property name that comes from the api and also i want to get the image the property for the image is this one and yes i'll give it an alias of image so i'll set up the section center for the entire section but like i said you can also set up a div if you want and as far as the return i'm going to return a article and then when it comes to react since it wants to keep the track of all the changes that are taking place we do need to provide a key prop which needs to be a unique value now technically you can get away by grabbing the index over here if you're familiar with map you know that the second parameter we get by default is the index so you can also pass it here but it's not suggested if the data is going to be changing so if you're going to be making some kind of manipulations with the data so therefore it's always suggested to have something unique and in our case that something unique is the id then we want to add a class name of a single meal and i'm not going to repeat the whole deal about the css and we want to display the image now with the image for now i'll just go with this style and width 200 so effectively we're setting up the inline styles here simply because otherwise those images are going to be massive so yes the css is coming up so for now this is just temporary now again if you have the entire css you don't need to worry about it just add the class name of img and then right after the image we have the footer where it will display the title and also the like button now the icon for the like button will set up in the following videos for now let's just right click me and then if everything is correct we should see some images some titles and all that cool stuff so let's start working on that where first navigate back to the meals here and i'm not going to switch back to the browser and showcase where i'm getting the properties again i believe i showcased that quite a few times so first i want to pull them out out of the single meal and yes each object has them then we want to go with string meal and yes the names are a little bit funky but we'll just live with that we'll just give it an alias and we'll move on and then the last one is the string meal and then i believe it's thumbnail and that is equal to a image at least that's my alias so i'm going to set it equal to single meal now we nicely destructured it and now let's worry about the return and i'll say not i forgot to add here the class name not class i'm going to go with class name that is equal to section center and then in here it's not going to be a heading 4 will actually go with a article and then another thing that's not giving me auto complete so let me type it here article as well we do want to add a class i believe here and the class will be single meal so class name is equal to single and then meal and let's also add that key prop that basically is looking for the unique value in our case that is going to be id meal and then once we have this one in place inside of the article we want to go with img so let's set up the image let's set up the source and insert it equal to the image to the alias that we gave to the string meal and then the thumbnail and then let's also add the class name right away as well and we're gonna go with img let's close it and then right below image we're gonna go with footer and then inside of the footer let's set up a heading five setting five and then in here we wanna display the title and right next to it we'll have a button and in here let's set up again a class name it's going to be a like btn and then for now it's going to be clicking but eventually we'll set up a nice icon as well and now let's see what we have as far as the result in the browser and of course as i was setting up i forgot that i need to add essentially inline style so let me go with style and in here i want to go with with and we need to remember that since it's javascript this needs to basically be a string and now let me go back and yep now it's more manageable again it's not pretty but at least we can see some images titles as well as the like button and with this in place now we can move on to the next step okay and now let's worry about the styles now like i already said i believe ten thousand times if you have the styles you can just skip this video if you don't then we'll type these styles together and first let's just start by navigating to app.css and i want to set up the comments so usually what i do is i set up the css in the order that i have my components so eventually we'll have the search web favorites will have the meals and we'll also have the model and therefore i'll do the same thing in the app css where essentially i want to start with search then it's going to be favorites and then we want to go with meals and lastly there's going to be a model so the search and favorites are coming up for now we'll just worry about the emails and we'll start by setting up that section center and you know what also i think it's going to be easier if i just place the tab over here so that way we can right away see what we are doing so start with that section center class and you know what i'll just make it here for now of course eventually i'll set it back to what it was start with section center we do want to add some padding here and i'm going to go with three rem stop bottom and zero left and right then we want to go with with and this is the case where i'm going to use my css variable which is i believe set to 90 view widths so essentially the percent of the screen and again the reason why i prefer this is variables because that way effectively i can just set up the value in one place reuse it in multiple places and if i ever want to change something well then i need to change it in one place then i'll also set up the max width so this is for the big screen essentially i don't want any of these components spanning the entire screen i want to set up some kind of max width which i believe again if you want to double check that just navigate up to the css variables i just don't want to do that since i know that some people find it annoying but i believe it was like 11 20 pixels or something along those lines again we're looking for the variable max with and now we just want to place it in the center so we're going to go here with margin 0 and then although you know what these warnings are a little annoying so check it out now of course our container is always going to have the width of 90 of the screen but it's never going to be bigger than the 1120 so it's always going to stay like this and then we'll write from the get go set it to display grid and i'll add some kind of gap and it's actually going to be the same for the rows and columns and i'm going to go with two rems i just always prefer pretty much that type of setup and since we're on a roll when we also right away set up the column layout for the bigger screens and we'll do that with the media query and we'll go with media screen and let's go with min width and i'm going to choose the value 776 pixels and then in order to speed this up a little bit i'll copy and paste that's going to be my section center and then we're looking for the property grid template and then columns we'll set it equal to one fraction and one fraction so once we get to 776 we should have a two column layout and as you can see that is clearly the result and then we also want to add one for the bigger screen which most likely i'll showcase right away as well so in this case it's going to be 992 and now we're looking for a three column layout now as i know i'm fully aware that we can change the syntax here to let's say repeat but i just think that for this project it's good enough if we just repeat those fraction values so now let me make it bigger and notice we have a three column layout and now let's worry about that single meal we are pretty much done with the container now we want to go with single meal and of course we're talking about that card we'll start with the background property and we'll use again the css variable with the value of white and yes pretty much the actual value is also the white color then we want to add the text color and this is going to be for the button so heading already should have the text color set in css but since i want to have the same color for the button i'm going to go here with color then var and then we're looking for text color so that's the easiest variable then let's add some border radius or radius and this one will set it equal to again css variable so far and then we're looking for border and then radius like so and then we'll add a little box shadow a transition both of them see if there's variables and then once we have already single meal we'll just change that box shadow so let's start here the box shadow and let me scroll up just so it's easier for you to see so we're looking for a box shadow property that one will be equal to a shadow to css variable and then we also want to add a transition simply because we want that change to happen over time and therefore we'll go with var and then transition like so and then let's select again that single meal and let's set up that hover effect so single meal and then as we're hovering we want to change that box shadow over here and once we save it we should notice that as we're hovering effectively we're getting that darker box shadow now one thing that i want to mention remember in the previous video we added that class of image now notice that this is a global class which adds a width of hundred percent a this block block as well as object fit so now once we have the structure in place as far as the columns and everything we can actually remove that inline style so now let me navigate back to the meals and you know what let me just minimize this for now and then remember we added this style and i said that it's going to be temporary so now once we have the columns of course we can set it back and you'll notice that of course the image is spanning all across and this is exactly what we wanted so now let me navigate back to app css make this one smaller and maybe this one also a little bit smaller just so we have a little bit more real estate and then we actually want to style the image right away so we have that global class yes that's awesome but we also want to add some additional styles and therefore i'm just going to go with img so effectively i'm targeting that element first i'm going to set up some kind of height which in my case is going to be 15 rem and now let's talk about the border radius notice here how we set the border radius for the entire card but we also need to set it for the image now i don't want the border radius for every corner i actually only want for the top left and top right in order to do that we just need to go with border radius and we need to add top and then left and yes you guessed it in order to set up the right one we just need to change this value around and now we should notice that the top left and top right corners are actually around it and then lastly as far as the image we just want to add cursor pointer because in the final application we'll be able to click on image and then we will actually display it in the model then let's style a heading 5 here so single hyphen meal and we're looking for the heading 5 and in here let's add a padding 0 margin zero because there is some default uh margin padding as far as the typography let's save and then let's worry about the footer so single meal and we're looking for the footer in here let's add a padding right away so padding is going to be one rem's 1.5 rms then we'll display it as flex so display equals flex we want to align the items in the center so say align items center we want to go with justify content and space between so this effectively is just going to push them as far as possible from each other so let's say here's space between and then lastly we also want to go with flex wrap and wrap so if there's not enough space we just want to wrap it to the next line so flex wrap and equals to wrap and even though we don't have the icon we might as well style the button since we're working with the css so let's say here like button that was the class name and then we're looking for the background we want to go with transparent and we want to add the border also transparent so take this value here copy and paste and then after that let's increase the font size again for text it probably won't look that good but once we set up the icon it's going to be good enough we're going to go with 1.5 rems so increase that then cursor pointer and again the transition so cursor pointer and for transition just so i can save a little bit on typing i'll just grab the value from the single meal and set it here and as we're hovering what do we want to do well let's add some transition so like button hover and then as we're hovering essentially we wanna change the color to red so color is going to be equal to a css variable and the value is red dark and also we want to transform so let's go transform and let's translate in the y direction and since i want to lift it up like two pixels i'll say negative two pixels so now check it out as we hover over the like button we actually lift the text up a little bit and essentially that is the css for our meals component and while we're still on a topic let's also knock out the icon and effectively for my project i prefer react icons library for a variety of reasons first of all it offers tons of options and second it's very easy to work with library because you get back the component the react component and as a result you can add the class you can style it directly and all kinds of cool things so if you want to utilize the search engine just look for react icons or you can just follow the link that i provided in the readme and once you get there you'll see this documentations page like i said uh you have tons of options so these are all the libraries that you can work with and if you want to search for specific icons so let's say in our case if we're looking for thumbs up icon just type here in the search box and i believe i used this one over here now don't quote me on that essentially i will showcase that in a second but i believe that's the one that i used and just keep in mind that once you choose the icon you also need to remember which library is it from because when you import the icon and as i say not the syntax is following where you go with the name you also need to provide the library otherwise essentially you'll get the error so now let me try it out in our application where first i want to go and install the package i believe the package name was a react icons and i should get the suggestion hopefully yep there is that's the package we want to install then we want to navigate of course to the meals that's where we are setting up that icon so meals over here and now let me grab right away the value so again let me search for it and that's the one that i want to use notice the name was copied to our clipboard and then we want to go with import get the icon from and then we're looking for react icons but very important you need to add the library in my case that is bootstrap and then where we have the like button instead of just click me i'm just going to go with this component and since i want to save a little bit of time on typing i'll just copy and paste the component now let's save it and take a look at the result in the browser and now check it out instead of the text we have a nice icon from the bootstrap library beautiful and once we're done with our meals component well almost done there is a little bit of functionality coming up but the main setup is done before we continue i also want to showcase why we want to use a user effect and feel free to just watch the video i mean you don't have to follow along because i will purposely set up the infinite loop just to kind of underscore the point that i was making previously so if i navigate to context js and if i decide to be a rebel and then instead of using the dependency array and for now leaving it empty basically invoking this callback function only when the initial load happens only when the component mounts i will actually get a infinite loop so let me showcase that let me remove that dependency array let me save it let's navigate to the browser and then more specifically we're looking for the network tab and notice over here notice the amount of requests that are we making so why is that happening well first let me go back and actually add here a empty array let's save it and then the reason why is that happening is because we need to remember that when it comes to use state every time we change the value of the year state we trigger re-render so now let's go step by step when it comes to our fetch functionality on the initial render when the component mounts we invoke use effect correct now instead of that use effect the callback function we fetch data and change their values for the meals so there is initial render and instead of the fetch meals we change the value for the meals state value now what happens when we change the value we trigger another render we trigger re-render now what happens in that next render well we repeat the steps essentially we repeat the steps 2 and 3 in here so since we triggered that re-render inside of the fetch data we go back to the step 2 and then step 3. that's why you'll have so many requests and eventually the browser will run out of those requests and effectively crash because you have infinite loop since we trigger rerender when we change the value of the state variable that's why we need to be very careful when we set up the use effect and refresh data keep in mind if you just have simply console log then of course it's not going to happen because you're not triggering that re-render but if inside of the fetch data or fetch meals whatever fetch function you have if inside of that function you change the state value which is our case of course then yes you need to make sure that there is a dependency array and if you're placing any values inside of it you need to have a clear idea when this callback function is going to be invoked otherwise you're risking setting up the infinite loop and then like i said eventually your browser will crash and the same goes if you'll invoke the function inside of the use effect so this is the question that i get quite often where students say hey but why do we need use effect why we can't just move fetch meals outside of the use effect well let's see you'll pretty much see the same result again let me save and let me navigate back and notice again we get tons and tons and tons of requests because we have infinite loop that's why you always always want to fetch data as of now of course things might change but at the moment in react you always always want to fetch data inside of the user and you want to make sure that you start at least with the empty dependency array and then eventually as you add values that you have a good understanding when this callback function is going to be invoked because remember once we start adding values over here we'll invoke this callback function and all the code inside of it once the values that we add there change and while we're still working with the meals let's also set up a loading check as well as empty meals effectively if we don't get any data back from the api first i guess let's start with loading you see when it comes to data fetching effectively it doesn't happen instantly because it is a synchronous operation now of course it happens fast meaning in the human time it's fast but it still takes a little bit time in the computer time and we can clearly see that if we navigate to a network tab and if we slow down the network so in my case i'm going to go with fast 3g and you'll notice that initially there's nothing on the screen we just have that empty array and only after time we actually display those meals now in my opinion a better setup is if we have some kind of loading condition where essentially we display something on the screen and to showcase that i'm going to navigate to a complete project and you'll notice there that we'll have this loading dot dot dot so effectively while we're getting the data we're just displaying to a user that hey we're loading it and then once we get the data then we display the emails and the steps in order to set it up are following first set up a state variable by the name of loading at least that's going to be my name and default value is going to be false now in the fetch meals the first thing you want to do is set loading to true so as we start fetching meals we set loading to true then the last thing that we want to do in the fetch meals is set loading to false so once we're done fetching data regardless whether we get back the data or there's an error we want to set loading to false and then we want to add that loading state variable to a value prop basically we want to pass it down to our application in the meals jsx we want to grab the loading variable and we want to set up the condition now it needs to be before our current return so if loading is true then we want to return loading dot dot and then once the loading is set back to false then essentially we display the array of meals and as far as my solution it's going to look something like this or like i said there's going to be a state variable in my case i'm going to call this loading and of course there's also going to be a set lowering function the initial value is going to be false and the notice in the fetch meals the first thing that i do will set loading to true so that's when we start loading the data and regardless whether we're successful or there's an error we sit loading back to false we pass down loading to the entire application so essentially we add it to a value prop and then in the meals i destructure it i say hey grab me loading and right before our current return i go if loading is true so while we're loading what we want to display we want to display section and yes we do need to add a little bit of style so i'm going to set it up as class name section in there i'll set up a heading 4 with the text of loading and essentially that's it and of course after that we have our return so the idea is that while we're loading this is what we display on the screen so now let me set this one up or first in the context i want to create that state value and i'll purposely set it up before meals that's just my preference so const and then loading then we also want to go with set loading now the initial value is use state and we want to set it equal to false then in the fetch meals let me call it so set loading is equal to true now let's copy and paste and then at the very end of the logic let me just set it up here as false so we're done with the loading then we want to pass this one down so let's pass in the loading as well and then in the meals we wanted to structure it so let me navigate back to the meals jsx and before or after the meals it doesn't really matter i want to grab the loading and before i return the array of items before i return my cards that have the info about the meal i also want to set up the condition for loading so if i'm loading there's going to be a different return and as a result we'll have that loading displayed while we're fetching the data so near like i said there's going to be a section with the class name of section so we'll have to add a little bit of css as well so let's go here with return then section let's add a class name right away in this case the class name will be section and then inside of it we're going to go with a heading 4 and the text of loading data so this is true this return will be displayed and then once this one is set to false then we'll render the array of meals so let's try this out where first i'm going to navigate to a browser let me refresh and if everything is correct we should see that loading displayed on the screen now we still do need to add css so let me just see whether the functionality works and if everything is correct then we'll proceed to css yep i can see the loading displayed and i'll let me navigate back to our application we want to look for app css and we'll have to grab some styles from the section center so that's already a modal i want to look for section center and before the section center i'll create a section class and we'll grab some values here from the section center so we want to take padding with max width as well as the margin and effectively there are two ways how you can set it up so you can just copy and paste the styles or there's another approach if you want to save some lines of code so if you are interested in the other setup we can also add a comma here go with section and center so now we're reusing these styles for both of these classes and then when it comes to section center we just add the extra styles that are not included over here so that's another way how we can set up the logic the result is going to be exactly the same where now we'll have a proper section and in there we'll have that loading condition so before we display the array of meals we'll also display the heading 4 with the text of data.loading and as i said we'll use an extremely similar setup for the condition if we get back no data from the api and i think at this point we can just go back to no throttling and up next let's handle the case if we don't get back any items from the api and i think the easiest way to showcase that is just by navigating to and notice at the moment we're using this all meals url and since we have a search time of a of course it returns some data but what if i type some gibberish over here let's say i'm going to go with five a's let me save it and then if we take a look at the meals app i mean don't see anything on the screen why well because we don't get back any data and the reason for that is because if we take a look at the api we can see that yes if the search matches some results we get back meals array but if the search that we type doesn't match any of the meals then we get back meals as now and if you want to see that just navigate to the api copy the url and just add some gibberish after the text they provided so if i just add s you'll notice that we have here meals no and we need to handle that case especially because eventually there will be a search input so the user will be able to type the search term and we want to display if the search term did not match any of the meals in the api as far as the setup let me find the readme here it's gonna go like this again i'll have to scroll down a little bit we want to go with fetch meals and in the case of success so in the try block we want to check if data meals is truthy basically if it's an array it's going to be evaluated to true in the if condition if it's equal to null then of course it's going to be false if it returns a true basically if it has some value only then we want to go with set meals and then data meals so at the moment we're setting pretty much our state variable regardless but we want to change it we want to set up if else condition and only if data meals returns true then we want to set the state meals as data meals otherwise we want to set it equal to an empty array in the state and then in the meals gsx we want to check if the length is less than one meaning we're checking for empty array and if that's the case again we want to return a section and in there i'll just type some error text now we want to place them in between the loading and the current return again this is very important because we start with loading then we want to display the error if it's there and then we want to return the list off cards and as far as my solution in the try block i'm going to set up if else in here i'll check if data means returns true if it's evaluated to true if that's the case then i'm going to go with set and data meals and if it's false then i'm going to go with set meals and then pass in empty array and then we don't need to pass anything down we're already passing down the meals in the value but in the meals gsx we want to add another condition where we're checking length of the meals if it's less than one same deal we want to return a section and in there we just want to provide some error code and most likely i'll copy this one since i'm too lazy to type it from the scratch but i'm going to worry about it once we get there so first let me showcase how we can also work with multiple files so if we click on this plus we can pick which file we want to display in my case i'm going to go with context and i also want to display of the emails one because that's the current file that we're working in and then back in the context like i said we just want to set up the if and else condition we're doing that in the try block so technically it's not going to be an hour since the api returns a status code of 200 which means that the request was successful it's just there's no data to return so in here let's go with if and then data meals if it's true then we'll set our state variable equal to that if not then we'll go with set meals and we'll just set it as a empty array then let's keep on moving and we want to go to the meals of course and here let's add that second condition we'll say if and then meals length is less than one what do we want to do well we want to basically return a text we just want to change the value over here so let me quickly run back to the readme and i'll grab these values so in here in the meals this is what we want to return so copy and paste and we are good to go so now let's try it out where i'm going to navigate to the application and if everything is correct if you didn't change the search term back to something that returned some items we should see this error message on the screen so now i want to navigate back to the context one and here let's just fix it where i'm going to go back to a now eventually this will be dynamic again that is going to be the case once we add the search input so at the moment once we fix yep everything is correct again we have an array of meals and up next let's work on the search component so in here user will be able to type the search term and if the term matches any meals in the database of course they will be rendered on the screen and also there's this option of clicking on surprise me where we fetch a random meal from the api and we'll start with the structure so first let's just get something on the screen and then we'll worry about the functionality so in the search component the search jsx import use state and use global context now please keep in mind they're not coming from the same place so one is coming from react and the second one is coming from our context then we want to set up a return and don't worry about the css yes it's not going to look pretty but we'll go with header we'll add a class of search container which of course eventually will style in the header there's going to be a form and inside of the form we'll have the input with form input class type text and then two buttons so right after the input we'll have two buttons one with class of btn and type of submit and the second one with the classes of ptm btn hipster and type btn the last thing that i actually forgot to mention over here in the app jsx we want to uncomment this correct so in the app.jsx display search component and once you're ready to see my solution proceed to the next video okay and i think i'm going to start actually with the last step so first i want to go to app.jsx and i want to remove that comment so let me just remove the code and now we should see a search component yep awesome then in the search let's start by importing both of those things the use state and use global context so first let's start with import use state and that one is equal to react so basically it's coming from react then the second one is use global context which is coming from our own context so dot or i'm sorry two dots and then we're setting up the context and then like i said as far as the return we're gonna go with header we'll add right away a class of search container so search container and then inside of it we want to go with the forum so as you can see this is an error it should be header here then let's set up that form component sorry element i guess more properly it's not going to have a class but we will have the input inside of it we'll set the type text and i'll also right away add the placeholder now technically you don't have to but i'm going to go with type then favorite and meal and also we want to add a class name and this is going to be form input let's close it and then we want to set up those two buttons so let's go here with button then type will be submit and as far as the text i'm just going to go here with search and also i want to add a class and it's going to be btn now copy and paste and i'm just going to add btn hipster the type will be good old button so go here with button and as far as the text i think we're gonna go here with surprise me so that should do it for the general structure now let me take a look yep and as you can see we've got a input with two buttons now don't worry we'll work on styles in the next video and the reason why the buttons are styled because the btn classes are already in the global css all right and up next let's style the search component since we have the structure in place and i guess i'm going to start by just changing these files around where first i want to open up a new one and this is going to be app css and then instead of the meals of course this will be a search since this is where we'll do all of our work so as far as the app css we have the mono okay that's good we already styled the meals we're not gonna work with favorites we'll work with search and this is the case where again i'll move this sucker here just so we can see what we're doing and let me close files for now and also maybe let's make this one a little bit smaller and then let's start by just styling the search container so let me grab the class here then i'll add some kind of height it's going to be 5 rems after that we want to go with background which will be equal to the state variable of white then we want to go with display flex so essentially we're setting this up as a flex box and we want to align all of them in the center so we go with align center and or i'm sorry align items line items and that will be equal to a center then we want to also place them in the center horizontally so we'll go with justify and content and that will be equal to a center so once this is saved we want to work with a form so basically now we styled the parent container now let's work with the form now it doesn't have a clash so just go with search container and look for the form element in here we'll add a width and you know what since the values will be exactly the same over here i'll just grab these two so this is going to be the width of container and the max width of container let's save this and then we'll make a form to be a flex parent as well so display flex and let's add a little bit of gap in between the items so 0.5 rms and then also let's go with flex wrap and then that one is equal to a wrap so if the size of the window gets smaller then of course we wrap it to the next line if you want to check it out just make it smaller and you'll see how we nicely wrap to a next line then we want to style the form input so let's go with search container then class of form input and here effectively we want to set up some kind of max with so this is not going to be bigger than in my case 200 pixels we also want to add a little bit of padding so let's go here with padding and then let's set it to 0.375 rms and then 0.75 rem's left and right so top bottom and then left and right let's add a border radius or radius and then this will be again a state variable so border radius and i also want to add the background as well as deep border so let's go with background that will be equal again to a state variable with a background color so this will match whatever i have for the body whatever gray color i have for the body it will be the same and then lastly we have a border here where we're going to go with one pixel solid and now i'm looking for one of the gray colors so far iphone hyphen gray and 200 like so so save it and then let's style the button and the placeholder so i mean we can i just style the placeholder first so in here let's say font family equals to inherit so now we're essentially inheriting the value and also let's add a different color so in this case it's going to be equal to bar and i think i'm going to go with gray 400 so just different shade of gray and then lastly let's style the button so we're going to go with search container and then class of btn and let's add a font size a little bit smaller so i'm going to go with font size and then 0.75 rams let's save it and we're pretty much done with the css so now we can jump back to the logic so let me just add a tab in a proper place and we'll continue with the handle submit and handle change logic okay so at the moment we have a good looking search component with the input as well as two buttons but there's no functionality and first i want to add handle change to the input so there's going to be a state value that is persisted between the renders and also i want to handle submit because at the moment you'll notice that once we click on the submit effectively we restart the entire application because that is the default behavior for the form and here are the steps that i'm going to take first create a text state variable and then we also want to set up two functions handle change and handle submit in the handle change we want to grab the event.target.value and please remember that by default it gets the event as a parameter and then we want to set that to a new text value so this one will have the set function and of course we want to pass whatever we get back over here into that set function now once we're done with that we want to add on change to the input and set it equal to the handle change and then when it comes to handle submit again we'll get back the object as a parameter and we'll just set up event prevent default otherwise again we'll have that default behavior where every time we'll click on submit we'll just refresh the application since the default behavior of the form is sending a post request and then we want to add on submit to a form element and set it equal to handle submit okay and as far as my solution so i've got text and set text the state value the initial value is equal to an empty string then i created handle change passed in the event since that's the parameter we get by default settext event.target value and the same deal with handle submit where event comes as a parameter and here i have event prevent default now i forgot to mention in the previous video that also for the input not only we want to set on change equals to a handle change but we also want to pass in the value so value prop and that is equal to a text so as a result we get the controlled input where every time we'll pass something in input the state will be updated and then as a result between the renders will also persist the state value and when it comes to the form we want to go on submit and pass the handle submit at the moment we don't have more logic but it will prevent that default behavior so let's set this one up where first i want to of course navigate back to the search component and then let's set up that state value so we're going to go here with const that's the whole purpose why we grab the use state so we're going to go here with text and set text and then that one will be equal to use state and we pass in the empty string then let's set up those two functions so const and i'm looking for the handle change now i'll grab the event object and then as far as the functionality every time we'll type something in input we're gonna go with set text and we'll pass in the event dot target dot value and also let's set up the handle submit so const handle submit and then same deal we grab the event object now the deal here is to prevent the default servant prevent and then default let's invoke it and now we just want to set up both functions so let's start i guess with a handle submit and we have a special prop for that we go with on submit is equal to a handle and submit the same deal here but we just need to add a value prop as well so let's start here with values equal to a text so now we're grabbing the state value and then on change so every time we'll type something in the input we'll also update the state value since we have the handle change so let's go with on change is equal to a handle change like so let's save it and let's take a look at the application so first let's check the submit notice now when we're submitting we're not performing a default action so we're not sending that post request so that's already a good start since we're not refreshing the application now the second thing is as we're typing we're actually persisting value in the state and if you don't believe me just navigate to the components and then if we navigate to a search component notice the state value and essentially as i'm going to be deleting the gibberish from the input i'll have the same result as my state value okay and now let's set up the search logic or essentially we can type something in the input click on submit and if there are no meals display will display error remember that's the one that we set up in the previous videos but if there are some meals that are matching the search term we nicely display them so now connect the search input with the meals that we are fetching and in order to do that in the context.js first we'll need to create a new state variable in my case i'm going to call this search term and the default value will be empty string then we right away want to combine the all meals url with the search term so prior to this we're all the time using all meals url but remember this is a hard-coded url so now i want you to remove that hard-coded value i believe it's a and then when we invoke fetch meals in the use effect i want you to combine all meals url with a search term then we also want to add search term to a use effect dependency array so every time that value changes we fetch new set of meals every single time then we want to pass the set search term because once we create the state value we also have the function that controls it and we want to pass this one down to entire application now of course in our case we'll grab it in the search jsx so grab this function and then in the handle submit if there's any text in the input then we want to set it as a value for the search term now optionally you can also set text back to empty value but that really comes down to the personal preference as far as my solution i created set search term and search term so that's the state value and that's the function that controls it and then in the use effect i passed in the template literal and i combined all meals url with the search term now keep in mind again we need to remove that hard-coded value of a in the all meals url and i also added search term to the dependency array so every time we'll change the value of the search term we'll perform a new fetch request and the new value of the search term is going to be used then we also want to pass set search term down to entire application so we need to add it to a value prop and then in the search jsx we wanted to structure it we already have use global context so we just grab it from use global context and then in the handle submit i want to check what is the value for the text if it's empty we're not going to do anything however if it has some value we can just go with set search term and pass in the text like i said optionally you can set it back to a empty string when it comes to the text but that really comes down to the preference so let's start in the context.jsx first i guess i want to remove that hard-coded value here in the all meals url so instead of a it's just going to be an empty value then we want to go with a search term search term and then comma set search term set search term and that was equal to a use state and we pass in a empty string then let's keep on moving we're not going to change anything in the fetch meals but we do want to refactor this one so like i said we're going to go with a template literal since now we'll combine both values all meals url with the search term so first let's access all meals url and second let's grab that search term search and term then we want to pass down the function that controls it so let's go with set search term and now let's navigate to the search jsx first we want to grab it so we're going to go here with const we're getting back the object and we'll invoke use global context and let's go here with set search term and now let's set up that condition so if there's any value in the text then we want to go with set search term and we want to pass in the text and optionally like i said i'll set back the text to a empty value so now let's navigate to the application and see what is the result so first let me refresh and let's take a look at the network so notice here how we're basically fetching without any kind of value for search and what's really cool that they do return some default meals that is already a awesome start and now let's try to submit the form so i have here the input i'm typing something and now i click on search now i can see that we set it back to an empty text so technically our functionality works but we're not performing a new request so let me quickly take a look here at the app provider and i can see that i have the value in the search term so now let's see why we're not invoking new fetch request and i think i know why so back in the context i didn't add the search term so this is what happens if we don't add this to a dependency array this will only run the first time on the initial render now in this case though if we add search term then we're good to go because now every time we'll change this value the state value will perform a new request now of course in this case we didn't get anything back so now let me go here and now notice these are going to be all the values with a and then if i type a b these are the values that we're going to get back now as i'm looking at it i think i rather just leave that text the state value for the input so let me quickly now get back over here and okay so this is optional this is up to you and i'm just going to remove it so in this case every time we type and we search for something we'll actually see what we just wrote and we'll be able to make basically modifications so in this case if i go with ad check it out these are the values that i'm getting back and successfully we have set up the search functionality okay and up next let's work on fetch random meal functionality so once the user clicks on the button surprisingly we want to fetch the random meal and here's my solution so in the context jsx i'm going to create fetch random meal and there there's going to be a fetch meals so the same function we already used before we just passed all meals url plus the search term in this case i'll just pass in the random meal url and then i'll pass it down to your entire application effectively i'll set it up in a value and then in the search jsx i will destructure it and for now so change this around actually in the following video because there's gonna be some bugs but for now i simply wanna invoke it once we click on a button so i'm going to set up a on click and i'll pass in fetch random meal and as far as the result it's going to look something like this notice we have all the meals and then once we click check it out we get our random meal so let's set this one up we're in the context.js let me keep on scrolling so i have my use effect um i think i'm gonna do it before the use effect and in here we'll just create that function now the name is really up to you in my case i'm going to go with fetch random meal that's a function and inside of it let's just go with fetch meals and then pass in random meal and url let's save it let's pass it down to the application so fetch random meal let's save that and then in the search we wanted to structure it so fetch random meal and probably at this point just copy and paste since it's gonna be faster and then where i have the surprise me button i'll add on click and we'll pass in the fetch random meal and now let's try it out so i'm gonna go here to the application click and yep we're getting the random meal and again the cool thing is that when it comes to the api the structure is the same yes we're getting only one meal but since it's set up in array we don't need to change anything here in the function in the fetch meals function we still get back to data and in there we have meals array and now we just set that meals right that one random meal equal to our meals state variable and then eventually of course we display it on a screen now there are some bugs and we'll fix them in next video but the general structure works yes we can fetch random meals once we click on the surprise me button so our basic functionality works as expected however like i mentioned at the end of the previous video we actually have a bug in our code and i think it's going to be easier to showcase it because i actually didn't pay attention that in the search jsx i still have the code to basically wipe the value and effectively the bug is following search term you know the one that we're using to pass it into the all meals url actually has the value and i actually want to wipe it so let me showcase the bug first let's imagine the user comes to application and we serve the meals that we get back if the search term is empty and let's say he or she searches for the meals with the search term of d okay awesome and then we go with surprise me so technically functionality works but if i take a look at the developer tools more specifically i'm looking for components and then the app provider notice here the value of d so that value is still here and that might be misleading since if the user comes here and types d notice nothing is changing why well because we only fetch new meals if the value changes and in our case we already have this d and let me just double check the name so we're looking for this search term so that's the one that's not changing now how we can fix that well what we could do in the search jsx we could set up a new function we can create handle random mule and in there we'll set this one to empty remember that's the one that we're using over here and we'll also set the set text to be empty and lastly we'll invoke the fetcher in the mill now there's gonna be another bug but first let's fix this and then we'll worry about that one so now i want to go to search jsx and like i said first i want to set up that handle random so before the return let's create another function so const handle random meal that's my function and here let's invoke a few things now in order to speed this up i'll just copy and paste so we have search term that one i want to set equal to an empty string the settext also is going to set it equal to an empty string and now i want to go with fetch and i believe it was random meal let's invoke this but now we want to change this around where it's not going to be fetch random meal we'll actually look for handle random meal let's pause that one and now notice that yes we nicely wipe out all the values but the problem is going to be that we set up another request and let me showcase that so again let's start from the scratch i'll just wipe it clean then i'll type d okay so we search for the meals then we go with the run the meal and technically everything works but i don't see the random meal now why is that well if we take a look at the network we can see that we're making two requests right now we have one for random and one for search now why is that well let's take a look at our code what are we doing here we're setting the search term back to nothing now why is that important well because we invoke this use effect every time this value changes so we fetch the random meal it's over here in the function but we also perform another fetch meals with the all meals url and here's the fix so first you want to set up another use effect in the context.jsx so this is going to serve the moment application loads at the moment application loads we get all males url with empty search them that's going to be again only when the application loads that's it now after that we'll set up another use effect and this is a good side note where you can have as many use effects as you want in your application you're not limited to one that's why i purposely fixed bug this way because i want to showcase that yes you can have multiple use effects now in the second use effect i actually want to check hey is there a value in the search term if not then just return what does that mean well that means that this functionality is not going to run now why is that important because if i'm not going to have this second use effect the first one then initially we're not going to get any meals because remember this is an empty value however now we fix both issues initially we get all meals url and then second every time we change the value we still check what is that search term if it's empty then nothing so that fixes our random meal bug so let's try this one out where in the context.jsx i have my first use effect and that's awesome we'll still have to add a little bit of code over there for now what we want to do is create another one and you know in order to speed this up i'm just going to copy and paste like so and here let's just remove the search term and rest of the functionality stays the same i mean technically we can actually remove the search term there's no need we can just go with all meals url and just to reiterate the value for the search term is empty but the cool thing is that the api still returns the emails and then in the second one we want to set up the condition where we want to go if there is no search term then we want to go with return and otherwise we want to call this and lastly in the search jsx i actually want to remove this one i want to leave the text that currently is displayed basically i want to display the search term so the user can see so let me navigate back again let me refresh notice how on the initial load we still display nicely all the meals okay that's awesome then let's say we're gonna go for the search term of f so we get the meals okay beautiful but once we click on surprise me first of all we get that one meal second if we take a look at the provider we'll see that this is empty so that actually matches whatever we have in input and lastly if we take a look at the network now we only have one request now we have only the random one awesome and with this in place now we can move on to the next step all right next let's work on the modal component and in the complete application it's going to look something like this where we can click on the image on one of the meals that we display effectively in the emails component check it out now we have that one specific meal and also we can click on one of the favorites one um it's also going to be displayed in modal and for now we'll just worry about rendering something on the screen because as we can see we don't even have the component and first i want to set up a return in the model jsx and yes we'll style these classes right away and you'll see in a second why because they are effectively responsible for most of the css features so the dark background and then the white color and all that so yes we'll basically style them first then i want to set up a state variable in the context.jsx i'm going to call this show model and set show model and the initial value is going to be false now yes eventually we'll control this once we click on the image here or on the image in the favorites but for now i just want to showcase how the logic is going to work and we want to pass this down the show model one and then in the app jsx remember we're not even rendering the model yet but we want to right away grab the show model now don't worry about the favorites actually this is an extra which shouldn't be in your readme so that one is coming up but in here we want to grab show model and of course we first need to import the use global context invoke it get the show model and display model only only if the value is true and for now we'll just toggle it manually just so you can see the basic functionality so first let me go to a search and let me change this around to a modal and then as far as the return like i said i'm gonna go with few classes that will style first and you know what also let's grab that use context let me see over here this sucker over here since we'll use it in multiple places we might as well copy it here so copy and paste so use global context eventually we will actually invoke it but not for now and let's go with aside then let's add a class name last name now will be equal to modal overlay as a signal that's the dark background that you see in the complete application and there's also tiny bug over here this should be a side and then inside of this element we're going to go with div and then we'll have a class name of modal container model container so that's the div with the white background where we'll see the image and all of the data about the meal and for now let's just say here a roll container or you know temporarily i'll add a heading 1 and i'll say modal container just so we can see it better all right so let's save this and then we want to go to the context we want to create that state variable i guess i'm going to do it right after the search term over here so const we're looking for show model then set show model so this is the function that we use to call it programmatically and as far as the initial value you know it eventually it will be false but since i want to showcase the modal i'll set it temporarily equal to true let's keep on moving then we want to pass down the show show model and we want to jump back to app jsx first we want to get the global one and again this is going to be the case where i'll just copy and paste i don't want to type it from the scratch so model here we just need to change the path of course so app jsx import and then it's in the same folder so it's only one dot then we want to grab the value the show model here so const show model and then that one is equal to huge global context let's invoke that and then where we have the modal at the moment we have comment around so we want to uncomment that but we will right away want to set up the condition we want to say only if show modal is true then so that's the end operator then we display the model so let me place it here and now let's see what we have since the value is true we should see right away model and now let me switch back to the context because that's the file where we'll be setting up most of the logic let me go back over here notice i have the model container why well because the value is true if i change this around in the context and if i set it equal to false where it is where it is over here if i set it equal to false bam we cannot see the modal nothing so we don't display the model so that's the basic structure for the model where we have the boolean state true or false and depending on that value we display or hide the model okay and up next let's work on the css so our modal actually looks more like this than what we have right now so at the moment we just have a heading one and yes i know i've said this already twenty thousand times but let me repeat one more where if you copied the entire css you don't need to do anything you can switch to a next video in my case i'm going to open up a new file and somewhere here i'm actually looking for the css one and the app.css is not coming up in my reset ones but we can always search for it like so and then let's keep on moving and if i remember correctly modal was the last one so let's work on those two classes and let me set it side by side right away like so and here let's first worry about the modal overlay so that's that dark background that we have the class is modal over lay and here let's set up position first of all fixed so it's going to be taken out of the normal flow then we right away need to add the coordinates in my case i'm gonna go with top zero and left zero so it's going to be all the way on the top on the left hand side then i want to set it width to be 100 and height to be 100 so effectively i want to take it up all of the screen with 100 and height also 100 and then we want to go with some kind of background so that's where we'll set up that dark background bang on property and i'm just going to go with rgba because the opacity value is a cool one that allows us to control how dark it is so for example in your case if you want it lighter then just change the last value the opacity in my case i'm going to go with 0.85 let me add here a colon so that's our modal and then effectively when it comes to the overlay i want to set it as css grid and place the items meaning our container in the center so i want my overlay to take up all of the screen but the items i want in the center that's why right after the background we'll set it up as display grid we'll also use the place items and center and as you know this is a cool property that allows us to combine align items as well as the justify content so instead of writing two lines of code you can write one then transition and i guess we'll have to write it here so transition that just can signals that the change is going to happen over time and we're going to go with var and then transition just this variable and then lastly we want to add the z index just in case there's some other elements that are taken out of the flow and we just want to place it on top of them so arbitrarily i'm just gonna go with hundred and now let's work on that model container and as you can see we already have the text technically in the center so this should give us a good idea how it's going to look like now let me select the class model container i'm going to go with width of 80 percent of the screen width and you know what let me add right away a background because it's going to be easier to see and we're going to go with the white so now we should see our model container then right after the width i'm going to go with max width so on a small screen it's always going to be 80 percent of the screen width now i don't want that model to be bigger than 800 pixels as far as the width now height always is going to be 80 view widths i'm sorry view height that's more proper so view height and then i know that the content is actually going to overflow i mean again if we take a look at this notice in here technically it didn't but if we take a look at the big mac notice so there is an image on the top and there's also the cooking instructions so now for sure that the content inside of it will overflow and that's why we need to go with overflow and just decide how we want to deal with that in my case i'm going to go with scroll and lastly let's go with that border radius just so we can have those nice rounded corners so border radius and we'll set it equal to var and then css variable with the value of poor radiators and we're pretty much good to go we have set our basic styles so now we can continue with the functionality beautiful and up next let's decide how we can pass the meal into the model so at the moment we just have a dummy content but of course eventually we'll have the functionality where once we click on any of the meals that we have here or any of the meals that we have in the favorite the data about the meal is going to be passed into a model and will correctly display and as far as the setup first i will create a selected meal and set selected meal in the context.js so again we're creating new state variable and initial value is going to be no then we want to set up a function that is going to be looking for two things the miele and also is it a favorite meal now we don't need to worry about this parameter for now we don't have the logic for it yet but eventually yes we need to keep in mind that we have two places where we have meals we have the favorites and also we have just a regular list so yes there's going to be a flag whether it's coming from favorites or is just a regular meal and then we want to look for the meal using the find method and we want to look where in all the meals in our state variable so if we remember here we have meals and then once we fetch those meals we set meals equal to whatever is the array we're getting back from the api correct so now we want to grab the meal id then we want to use it to get the meal in the array and we want to set it equal to our selected meal state variable and also we want to showcase the model now what was the function that was set show model then we want to make the select meal and selected meal available to rest of the application so we want to pass it into a value and then back in the meals we want to grab select meal so that's the function over here the select meal and then we want to invoke it once we click on the image so we want to add on click and pass in the id and i'll talk about why we need over here this arrow function again few things state variable the function we want to pass both of those values down so selected meal so this is what we're going to use in the model and select meal which we'll invoke in the meals so let's go step by step first let's create that state variable and in my case i'm going to call this selected meal so effectively what meal we have selected set selected meal now that is equal to use state and by default let's set it equal to no so by default it's not going to have any value but i also want to change this one around where it's going to be false so by default we're not going to display the model let's come up with that function and i think i'm going to do it right after the random one so let's create it const select meal and here the function is looking for two things for id meal effectively that is the meal id i'm just using the same property name as it comes from the api because that way it's going to be easier to understand at least in my opinion then we want to go with favorite meal which is a boolean value but at the moment we don't really care about it and we're going to go with let meal so initially it's nothing that value but we want to go with meal and then meals fine now why we're going the long way because there's going to be an if condition so for now yes there's only one possibility where essentially we'll just use this id meal and we'll get the meal from our array again we'll get the meal from our meals array so let's go with find method and pass in the callback function i'll reference each and every meal there as meal and i'll say get me the meal whose id matches the id meal basically whose property is exactly the same so id meal is equal to id meal that we're passing in and then let's set up two more functions first let's go with set selected meal so this is the meal display in a modal that's where we pass this value and second we want to open the model correct so set show model and let's set it equal to true let's save that and now we want to pass down two things we want to pass down the selected meal and we want to pass down the select meal so let's look for the value selected selected meal and we also want to go with select meal and now we want to navigate to bum bum bum bum css even though we will use it later we want to navigate to the meals we want to grab select meal and then let's look for the image now let's shall we destructure the idemill correct when we iterate over our so now we can just grab this value and pass it into a function now let me first showcase what is going to happen essentially if we don't pass in the callback function because this is the question that i pretty much get all the time as far as react so let's go over here and let's say select meal and let's pass in the id meal like so let me save it and you know what for time being let me just add a console log just so we can see that we have called this function because effectively it's going to be invoked right away and that's not what we want we want to invoke it only when we click on email so let me try here uh hello let's see let me save the application which you'll notice that first of all we'll open up the model right from the get go because that's the logic and also we'll have these 25 meals now why do we have that well simply because like i keep saying if we set up the function this way we invoke it right away so the moment application loads the moment we display the meals we invoke it but that's not what we want to do we want to invoke it only once we have clicked on it and the solution for that is following where we want to go with a arrow function and then we want to set up this function as the return from the arrow function and as a result you'll notice that everything works as expected so we get our array of meals and only once we click on it we shut that selected meal again the reason why i'm spending so much time on this because this is probably top three questions i get why we set up this arrow function simply because if you don't have the arrow function you invoke it right away and that's not what you want to do you want to set this one up as a return from the arrow function so initially this arrow function runs returns this function and then we invoke select meal passing the id only only once we click on the image let me also do one more log in this case i'm going to go with id email just so we can see that we're passing in that value so let me go back to my application first of all you'll notice that we'll display the modal because remember we go with set show model and we set it equal to true so bam check it out we right away display them all and also we'll have here the id now we don't have a way how we can close the model so that's why i mean it's just going to be sitting there right now but lastly in this video i just want to showcase that if you go to components you should also see this one what is this that's the meal that we selected how do i know that well because the idea is exactly the same so that's the state value the selected meal one initially it was no and now it's actually equal to the meal that we selected all right and up next let's render the meal that we have selected and also let's set up the close model functionality now dcss will add in the following video so if it looks somewhat ugly during this video i mean it is what it is the most important thing uh is to get the data on the screen so i want to showcase which meal we have selected and i also want to close the model and then we'll worry about the styles so first in the context.jsx and for some reason i have context and most likely i'll have to fix it in multiple places but again that's my problem we want to create close model and in here we'll go with set show model and we'll set it equal to false now we'll pass it down to a application so add that into the value and then in the modal we want to grab two things we want to grab selected meal like i mentioned in the previous video so select meal we utilized it in the meals now selected meal will utilize it in a modal so grab both of those things close model and selected meal we'll destructure again a bunch of properties out of it so image title instructions as well as the original source and then we'll work on our return and all the way in the bottom there's going to be a button that allows us to close the model so let's start working on that one i guess first let's go to a context one and we want to create the closed model function so again i'm going to do it before use effects and it's really up to you where you want to do it so close model and as i said yes of course you can pass in set show model but i always prefer just setting up the function makes a bit more sense to me so set show model we want to pass in as false of course because we're closing the model let's add a comma close model and we're already passing rest of the stuff so we don't need to worry about it after that we want to go to a model and we want to invoke that use global context and we want to grab two things we want to get the selected meal again this is the meal that we want to display this is the meal that we set once we click on those images and second we want to grab close and modal and that is equal to use global context let's invoke that and we're good to go then let's destructure it because we actually want to display it and you know what let me just mess around a little bit let's set up a button here just so we can close it let's write closed and let's set up on click now in this case we don't need to invoke it meaning as a arrow function we can simply go with close model since this is a reference again we're not invoking when you're invoking that's when you need to set it up as an arrow function now we don't invoke we pass it as a reference and then you know what let me just display the title just so we can see that we're getting that exact meal and this is also something that i suggest doing when you're building the application try to do it step by step um if you'll set a bunch of logic and then it turns out that you have a bug somewhere else this is going to be very painful to go and pack so that's why i always like to do it step by step where first i just display the title see that i'm actually getting the correct meals and then i proceed to the structure of more properties so in here i simply want to go with selected meal so for time being i'm not going to structure it i'm just going to look for the entire object and we're going to go with dot and i believe the value is sdr meal and now let's try it out what do we have let me refresh just so everything is up to date yep that's the meal that i selected i can clearly see that and i can close the model and the next one next one and i can clearly see that my initial functionality works so now it's just an easy part where we wanted to structure it and that is coming from selected meal and then one by one let's grab those properties again we do want to get the image so this one is that annoying one thumbnail that is equal to an image now sdr meal equals to title in my case then instructions and as i say not again if you want to see all the properties that are there in the object either you can log it here in the model or you can simply go to developer tools more specifically to our components and analyze it so let's go here with instructions set it equal to text and then lastly source and effectively this is the original uh kind of resource so let's keep moving we're not gonna have the heading one here and actually button the button is going to be another div so for now let's just leave it the way it is so first in the container we want to set up a image so let's go with img source and then image and i'll say not yes i know that i'm not setting up the alternative attributes and maybe you know let's change it let's pass here the title and you can also do that in the meals my apologies i forgot when i was setting up the meals so let's go here with a class names and we want to set up img and modal img so this is the global class and this is the class which we're going to style in the following video then right after the image we want to set up another div with a class name of modal content modal content and we want to place that button inside of it yes it's going to be all the way on the bottom but different div then let's go with heading 4 we're going to look for the title after that we want to go with a paragraph and we're just going to say cooking instructions and then let's set up another paragraph with a text so let's look for the text over here and lastly we have that original source so for that we're going to go with an href attribute we'll pass in source and i also want to open it up in a new browser tab so therefore i'm going to go with target and then underscore black again this is effectively a html attribute so let's pass here the value for our link and that is going to be original source and let's see how bad the css looks let me navigate here again i'm going to refresh so everything is up to date and then let me click on this one and there is a issue okay so select meal is not defined okay that's interesting so select meal is not defined modal jsx probably i just messed it up as far as the name so let me go here and yeah of course it's selected meal my bad see how easy it is to make a silly mistake let's try one more time and yeah i mean it looks ugly correct but as long as we can see all of the items so the image the title the cooking instructions as well as the original source we're good to go because we'll set up the styles in the following video and as far as that target blank check it out once we click on it we navigate to the original resource essentially where the recipe is coming from not i also noticed that in a context i still have that log so let me remove that sucker and just like that we're done with the functionality of displaying the selected meal as well as closing the model so up next let's style our model so it looks a bit more presentable okay and up next let's work on the styles so at the moment we have all the functionality but it definitely can look better and i'm going to start by navigating to the app css yep over here we're looking for the model which i believe was the last one and we want to style the image first then let me grab it here just so we can see right away the result and i'm going to start by targeting the image the modal img and i want to add some kind of height so it's always going to be 15 rams now of course that is up to you you can make it smaller bigger uh that is essentially irrelevant then we want to add the borders for the image because at the moment we just have for the container so in my case i'm going to look for those properties here so board top left and border top right let's copy and paste that essentially it's going to be faster then for a modal content first let's select the class then let's add a padding one rem's top bottom and then 1.5 left and right then for the content effectively for those paragraphs i want to add the great color model content and then paragraph and that is going to be gray 600 that's the value color var css variable gray and then we're looking for 600 after that we want to style the link so this one over here the original source and also the close button and you know what i think i think there's a button missing and yep so it's actually btn b10 hipster and close model i didn't add those classes my apologies so let me navigate back so class name we're gonna go with btn btn hipster and then we'll add close and btn let's save that that should do it let me click yep that's the button right now and then back in the css we want to target the button you want to look for that closed model i believe or close btn the one that i basically just set up and we want to add the background color different so let's go with close btn and we're going to go with background and we're going to set it as a red hyphen and dark and then after that let's go with color and we're going to set it equal to a white one all right so that should do it for the button and then lastly let's worry about that link so that's going to be under modal content and link in here let's go with display block because i want to start in the new line i want to set some kind of color in my case i'm going to go with primary and 500 then we want to add a little bit of margin in the bottom so my case i think i'm going to go with 1rms margin bottom equals to 1 rm then we have text decoration which will set it equal to the underline text decoration and that's equal to a underline let's save it yep looks about right and then lastly we just want to add a little bit of transition since there's going to be a hover effect as well so first let me select here let me add hover so as we're hovering we want to set the color equal to a black and then let's add that transition and that one will be equal to a css variable with the same name transition and once we set the styles we're pretty much done with the model and up next we're going to work on the favorites component and as far as the favorites we want to start in the context jsx we want to set up a new state variable by the name of favorites we also have a function set favorite and for timing is going to be empty array eventually we'll set up the local storage so once the application loads we'll check the local storage first but for now let's not worry about it we will set up two functions one is going to be add to favorites which again will look for id meal basically the email id then we'll use that id to find a meal in the meals array after that check whether it's already in the favorites so essentially if i have that meal and a favorite i don't want to add it one more time and if that's the case then we'll just return so nothing is going to happen if not if it's not in the favorites then we'll spread out the current values the favorites one and we'll add that extra meal so we create a new array we spread out the existing values and we add that extra meal and then we use the set function to actually add the new array as our value so we have the current value and this is the new one and while we're on topic right away let's also create a remove from favorites so this one again is going to be looking for id meal and we'll invoke it from the favorites same deal however in this case we right away look in the favorites and we just say look return only the meals whose id does not match the id meal that we're passing and again we go with updated favorites so now we use set favorites and again we pass in the updated favorites so all the time we just change the values in the array and we set that array as our new state variable we want to pass both of them down to your entire application so pass both of them in the value and for now in this video we'll just worry about adding to the favorites so we'll have to destructure it in the meals and then notice how it's exactly the same as select meal why because again we're passing in the id meal so hopefully you remember why we're setting up that arrow function so here we have that like button and every time i click on that button we'll add meal to the favorite and i guess i'm going to start by setting up that state variable i believe that's going to be actually our last one if i'm not mistaken so favorites then set favorites and we'll use use state then like i said before for now it's just going to be empty array let's keep on moving and i'll set up both of these functions here const add two favorites it's going to be a function and it's going to be looking for one thing and one thing only the meal id which i'm going to name id meal just because that's the name of the property so i think it's less confusing copy and paste and we want to go with the remove remove from favorites after that let's set up the logic so like i said first we want to get that meal from the meals state variables const meal and that one is equal to meals find and let's pass in the callback function i'll reference each and every meal as a meal parameter and i'll say if meal id meal matches the id so the parameter we're passing in if it matches the meal at the property then good then get me that after that we want to check if it's already in the favorites so const and then already favorite and that will be equal to favorites and we're gonna go with find check for meal and same deal basically if the id matches then this is going to be true so in here we can kind of cheat a little bit where i'm going to grab the logic again it's the same deal keep in mind that once we get this meal and we pass it into array the structure is going to be exactly the same that's why we can do that uh now let's set up the condition if it's true if already favorite evaluates to true in this case then i want to return why because like i mentioned i don't want to add it multiple times to a favorites i mean if it's already there then i'm good to go so that's why we can click all day long and nothing is going to happen that's exactly the result i'm looking for and then lastly if that's not the case then javascript is going to keep on reading the code and therefore we'll create this array update favorites and now will be equal to a new array let's spread out all the values in the state in the state variable let's add that meal sucker over here and then let's go with set favorites and let's pass in update favorites now eventually yes there's going to be a local storage but for now we're not gonna worry about it so we're gonna go with updated you know what i need to actually fix this updated and then favorites all right that's good so now let's set up the logic where we remove from the favorites and we'll do that by again creating a new variable updated and then favorites and we're gonna go with favorite state value and we will use the filter method and we'll check if the item id mail property does not match the id that we're passing then we'll return it into our new array so essentially we'll just exclude the item whose id matches and as a result we'll be able to remove the meals from the favorites area like so we click and we're good to go and this is going to be the case where again we want to pass in the callback function and we want to go with meal and as i said i need to set it up here as a param meal and if meal id meal does not so this is the case where we're looking for the items whose id does not match what we're passing then we return in that new array and now we want to do the same thing over here we want to go with set favorites and then passing updated favorites and then let's pass both those things down so it was add to favorites and it was also removed from favorite and once we have this one in place we just want to go to meals and then we want to structure it of course so say add to favorites and now let's keep on moving and we're looking for the light button so here we want to add again on click and yes i'll repeat one more time since we invoked a function basically there's no other way for us to get the id email we just have to pass it in and since we invoke it yes we need to set up the arrow function so let's go here let's say on click um set up the arrow function first let's see i think i have a mistake here and then we will invoke add to favorites and then let's pass in the id meal and if everything is correct uh we'll definitely see that in the components essentially in our developer tools but if you want to double check that you can always console.log so let me go back to the context let me find this one and i'll just log for time being and i'm going to pass in id meal so let's try it out i'm going to navigate to my application um i mean you can pick any of the meals and then just click on like button and we should see in the console some logs and also like i said if we check the dev tools either in the app provider we should see yep notice over here so that's the favorites array effectively every time we'll click on it we'll add the item so let me try here notice now i have three of them then this one is already here i guess that's why i don't see it and then notice every time we click on the item we add it to the favorites all right and now we just need to worry about how we can render it on the screen and as a quick sign up if you want to make your code more performant you can refactor meal below the return so essentially if you move the meal below the return now you'll see that we only search for the meal twice in the favorites and in the meals if we already know that is not in the favorites since we know that if the meal is in favorites we return regardless so if it's not in the favorites yes then we go to meals we get the meal and then we add it to the updated and you know the rest all right next let's worry about rendering the favorites and the first thing we want to do in the app jsx we want to grab the favorite state variable and we want to check the length and i only want to render favorites if the length is bigger than zero it's an array so we can always check the length and only if it's bigger than zero then we render the favorites and effectively the result is going to be following if i have no items in the favorites then we're not rendering the component all together and once we have that set up in place essentially we want to grab favorites select meal and remove from favorites in the favorites component so this is an array that we're going to render so if i add it here norrish that's going to be our component that's our array and then we want to grab the select meal because like i mentioned previously yes we'll be able to open up a model from the favorites as well now there is a gotcha but we'll worry about it later now we just want to grab this select meal and then we want to also grab remove from favorites so that's the remove button that we can invoke over here um for now we'll just set up the return where we'll have some heading 5 as well as we'll iterate over the items and then in the following video i'll worry about the css again the result after this video probably is going to be somewhat ugly so let's start cracking and i think i'm going to go to app jsx first and i want to grab the favorites as well again that's my array and i want to check the length and only if i have some items in there then i want to render the favorites component let me go favorites and as i say not keep in mind that every time you refresh it we'll start from zero from empty array simply because we are not we're not using the local storage yet so let's go here with favorites and then let's check the length right away length and if it's bigger than zero then we want to render the favorites so let me add the component in the expression and we're good to go and we can actually quickly test it so let me go to my application refresh and it looks like i have an error it says here that we cannot read the properties of undefined and i think it's because i didn't pass it down in the previous video my band so let me go here in the context jsx let me add the favorites array so we also want to pass that one down and now once we refresh we should be good to go so at the moment we don't see anything again it is empty array but once we click on the like button we should see the favorites component because now we have some kind of value in there and let me go back to my context.jsx i think i'll remove this one for now the id and then we want to navigate to the favorites that's the component then i guess i'm just going to start by again grabbing that use global context so let me look for favorites i mean here let's set it up since we'll grab a bunch of values from the context and we'll start by setting up the structure so const we're looking for favorites then we also want to grab the select meal again that is coming up for now we're not going to worry about it and we want to remove from favorites hopefully that one i added to the context.jsx so use global context let's invoke that and now let's set up the return it's going to be a section we'll add a class name of favorites last name and set up equal to my favorites then we want to rename the closing tag so this is going to be a section inside of the section let's go with div so let's set up the div and in here let's add a class of class name first of all and then we're gonna go with favorites and content then inside of the div let's go with heading five and we're gonna go with favorites and then let's iterate over that list however we'll place it in the div so they have class name and we're going to go with favorites and container and instead of div let's iterate over that array so favorites array then we'll call the map and we'll set up the callback function i'll reference each meal as an item and then as far as the return um we want to go with constant we wanted the structure again how do i know that it's there because we're passing that entire object to array so i know that the structure is going to be exactly the same again what we're looking for we want to get the meal and we want to get the image that's all so in this component it's not much and in this case i'll rename it to an image and that is equal to an item then we want to return and we're going to go with div we need to pass in the key prop and in that case it's going to be equal to id meal then we want to set up a class name here class name and that one will be equal to a favorite item item and then instead of this dividend by the way i need to add the closing one inside of this div we first want to display the image and then we want to go with the button that removes that item from the array so let's start with img source will go with image again that's the alias that we just set up then let's add a class name class name and that one is equal to a favorites and then img and also img so global image class and then the favorite image class and lastly let's set up that button we'll add a class name and that one will be equal to a remove btn so this is the case we're not going to add that global class we'll just set up a class 4d favorites and then inside of the button let's just type remove and we need to add the functionality correct so again we go with on click and this time i'm not going to repeat why we use the arrow function please we'll watch the previous videos where we initially set it up so let's go here we remove and then favorites so let me set up the proper name here remove from favorites and let's pass in that id meal and once we're done typing out the return we can take a look at the application again i can guarantee you it's going to be somewhat ugly so let me click here and notice that's our giant image and then we also have that removed so if we add another one then yep it's exactly the same thing and now if we click on remove we can remove from the favorites so our next step is going to be to set up the styles so it looks more presentable like this and as far as the css let's navigate to your app css and all the way no actually no not in the bottom i have model in the bottom we want to set it up here between the meals and search first we want to grab the main container and let me set up the files here as well and we're gonna go with favorites let's add a background and we're gonna go with black one now of course keep in mind that we're not gonna be able to see so maybe um you know what either we can add a favorite just so we can see something or we can remove that condition i think i'm just going to add that meal and we should be good to go let's add a color here that one will be equal to white one then we want to go with batting one rem's top bottom left and right is going to be equal to zero we'll set up the favorites content and essentially i want to set up the width similarly to how we did for a search so let's go with favorites and content and i'm going to go somewhere and find the values essentially this is what i'm looking for so with max with as well as the margin 0 which in this case i don't have i'll have to add it so copy and paste and let's add margin zero auto so now we're placing nicely the content in the center then we want to work with the container so in this case we're looking for favorites and container noun will be equal to display flex and then gap so set up a little bit of distance in between the items and also go with flex wrap equals to wrap let's say that and as a result let me refresh it should look better and nope it's still quite big ah because of the image yeah my apologies we're not going to see anything as of yet but we do want to place everything in the center and when i say everything i'm actually talking about the button so favorite item and then we want to go with text align and center save that and now let's make that image quite small so favorite hyphen img and we're going to go with width 60 pixels so now it's going to be small i mean it should be favorite img and then let's check we have poor radius or radius 50 and for some reason i don't see the result let me try one more time again still it's massive so let me double check in the favorites so that should be favorite item and this is favorites mg maybe i'm selecting it wrong so apps yes yeah should be favorites img my bad so now notice we have image with border radius as well as the width so now it looks a little bit better then let's add a border and that one will be equal to 5 pixels solid and we're going to look for the css variable with a value of white and then let's also set up a cursor pointer since remember once we click eventually we'll add it to a model and now let's worry about the remove button so that one is the last thing we want to style essentially for the entire project so let's go with remove iphone btm and here we'll go with margin top and we'll set it equal to 0.25 rem then we want to go with background transparent we want to set the color equal to white so r and hyphen white after that we want to do the same thing with the border so let me copy this one let's just set the border so borders equal to transparent as well cursor is going to be equal to a pointer and what else what else what else we have transition since there's going to be a hover effect and also a font size so let's start with font size that will be equal to 0.5 rem so i'll basically make the text smaller and then after that we want to go with that transition so let's go with transition and the css variable with the same name so transition and let's quickly add the hover effect so we're looking for a move button and we want to change the color essentially as we're hovering so remove button hover and then let's just go with color bar and then red dark let's save it and now notice we have the favorites we can only see it if we add the meal and you know what i think you can place it already there and once we add to the list we have more meals if we want you can remove it as well and once i remove all the meals then of course we cannot see the component the favorites component okay and next let's refactor select meal see eventually i want to add the same logic to the image so every time we click on a favorites image we also display the meal in the model however we need to keep something in mind we have two arrays we have meals and we have the favorites and at the moment select meal is looking where it's looking in the meals so yes there's going to be some situations where the meal that you have in the favorites is also going to be displayed on the screen however if let's say i go with a random one now as you can see if you click on this meal and try to find it in meals it's not going to be there anymore so when we set up the select meal we also need to take an account that we'll call it in two places on the meals array and also in the favorites and therefore we have right now this favorite meal and effectively we just want to add the condition so we want to add the condition that if that is true so if we're calling it in the favorite meals then we simply want to look for a different array so then we want to look in the favorites one now if it's actually in the meals then of course we don't need to worry about it it's going to be right there in the meals array so therefore we'll set up the condition we'll say if every meal is true then we'll look in the favorites if not then we'll look in the meals and then in the favorites we already structured it we just need to invoke it we need to pass in the id meal so the meal id and also true because in this case we're calling it from the favorites i guess i'm going to start in the context and first i want to set up the logic i'll say if and then favorite meal you know if it's true then essentially the logic is going to be exactly the same the only difference is i'm looking in the favorites let's call it and we also want to place the second one in the else condition so now depending on the value of favorite meal we'll either check for the meal in the favorites or in the meals and now we just need to go to the favorites we already have select meal and we want to add the on click on the image now let's pass in the function first the arrow function and then we want to go with select meal then let's pass in the id so we're looking for id meal and second we'll pass in the true so yes we're calling this from the favorites and now let's check it out i'm gonna go to my application so notice now all the meals now i can add it to the favorites and even if my meals are right right now is different i can still display them in the model which is awesome all right and the last piece of functionality we want to add to this application is adding favorites to the local storage so at the moment everything works nice but the moment we refresh the application again we start from the scratch and instead we want to save to local storage every time we add item to the favorites and we can do that for both of them for add favorites and remove from favorites so when we want to add the item to the local storage we go local storage again this is built in the browser so we don't need to install anything we go with set item in my case i'll call it favorites and remember that we can only uh save strings so therefore we need to go json stringify and then updated favorites so this array over here and then once we want to remove again basically we'll overwrite so we'll go with local storage set items favorites and then we'll overwrite the existing value with the new updated favorites and then once the application loads we want to grab it from the local storage now there's various ways how we can set up the functionality that grabs the items from the local storage but in my case i went the long way since that way um in my opinion it's more straightforward now can you make this code shorter absolutely but initially i wanted to make it uh easy to follow so here we're looking for the favorites we try to grab the favorites from the local storage we go with get item now there are two possibilities if the favorites exist then this is going to be true and then we just need to parse it because remember we stringify it so now we need to parse it and again we go with local storage get item favorites so we parse it back into array and that is if it exists if not if this is false then we'll set it equal to an empty array we return the favorites and then we invoke this where we have used it again i'm fully aware that there are shorter ways how to write this logic but at least when i'm setting up the content i always want to start with more readable code i think that is more important than having less lines of code and i guess i'm going to go to the context first let's just add the functionality where we want to go with that set local storage or sorry local storage and then we're going to go to set item we're looking for favorites at least that's how i'm going to call it and we need to use json then stringify and we want to pass in the updated favorites now once that is in place we want to copy and paste then essentially we're doing the same thing when we remove the item and here it's actually a bug because there's a missing letter and then let's scroll up and let's set up that function so we want to go with that get favorites from local storage and i'm going to set it up above the app provider we're going to go const get favorites from local local storage it's going to be a function and right from the get go it's going to return the favorites something we're going to set up right here we'll go with let and favorites now that is equal to a local storage get item and now of course we're looking for that favorites all right favorite if it exists awesome we'll have one logic if it doesn't then of course we'll just return an empty array so say favorites is equal to an empty array effectively the functionality we already have but if it does exist then it's going to be different we're going to go with favorites then json parse so we need to parse it again we are saving it as a string so we need to parse it and then local storage and essentially we just want to get this code over here let's just set it up and the last thing we need to do is just invoke it so where we have the favorites let's go with get favorites from local storage let's invoke it so now let's take a look at the application essentially once we add the item to the favorites it's displayed and also it stays there even once we refresh the application with this in place we're done with application hopefully everyone enjoyed it and i'll see you in the next one i hope that project helped you gain a deeper understanding on how everything fits together and react in this next section you'll use what you've been learning and also learn about new react features sanjeev is your instructor for this next section hey everyone for this next project we're going to be building out a stock trading app where users can keep track of their favorite stocks they could see what is the current price as well as historical prices as well now for this application on the main page you're going to see a list of all of the stocks the user has decided to watch and it's going to list out the last price or the most recent price as well as what was the change the change percentage the high low open and the previous close so just some relevant information about that specific stock and how it's doing in addition to that a user can go to the input field up here and search for companies to add to their watch list so if the user wants to search for tesla they can just search for tesla and this is going to send a request to our api and it's going to result in a list of companies that match that specific query we can then pick the specific company that we're interested in and it's going to add it to the watch list so now we can keep track of tesla and if we want to we can remove any one of these so if we want to remove microsoft we can do that as well and the nice part about this is this watch list here is going to be remembered because we're going to store this information in the local storage so if the user navigates away from this page and then comes back to it it's going to remember all of the companies the user is interested in now when we select on one of these stocks it's going to take us to the detailed page for that stock so it's going to render out a nice chart that's going to show historical data not just the current price so right now you can see that it's selected the past 24 hours if we want to we can also see the past seven days and then if we want we can also see the past year and the nice part is it's going to color code it depending on if the stock improved or if it went down and then beneath that it's also going to include some relevant information about the company so things like what exchanges are part of when was the ipo date what's the website for that company how many shares outstanding as well as market cap and a few other details now for the technologies in this project we're gonna be working with a lot of different technologies we've got all of the core hooks like use state use effect but in addition to that we're also going to be making use of the context api so that we can pass data down to the various different components in our application we'll get a chance to work with local storage and in addition to that we'll also be making use of the finhub api so that we can get data about these stocks and for the charting library we're going to be making use of apex charts so in the detail page when we draw out that historical data we're going to be making use of this library and you'll see that this library is actually very easy and intuitive to use and so that's what i've got in store for you guys hopefully you guys enjoy this project and i'll see you in the next section while we get started in bootstrapping the project and just a quick note before we proceed any further because we are using a free account on finhub api uh you'll see that we won't have access to certain data points so when you're looking for companies uh and if you're searching for something like microsoft in this case you want to make sure you just see microsoft you don't want to see microsoft.sw or mi these are not supported with the free tier and you'll see that it'll actually break our application just because we don't have the specific error handling checks for when the user doesn't have the privilege to access the information so just make sure you don't select on these and get the the main stock symbol before we get started bootstrapping our application i want to go over how we're going to handle navigating between the different pages in our application and so in our application we have two main pages when the user navigates to the root path and if you aren't familiar with what that means if you take a look at a url we have http colon slash and then we have a domain so this is gonna be whatever domain name you've purchased for your application uh and so if you own google.com then this is gonna be google.com if you're just working in development mode for your react application it's gonna be localhost colon 3000. so that's a domain and then you have a path following that so in this case this is called the root path because it's just forward slash so there's no specific path after that and so when the user navigates to the root path it's going to take him to the main page here where we're going to have a list of all the different stocks that they're tracking and when they select one of these specific stocks it's going to take them to a detailed page and that detailed page is going to reside at this following url so we have the same http colon slash we have the domain name and then the path is going to be detail slash and then the name of the specific stock so if they wanted to see microsoft it would be msft uh inserted in for symbol and so that's how we want the routing working in our application and the way we're going to actually accomplish this is through client-side routing and we're going to make use of a library called react router and react router is actually very simple and the main idea behind react router is you tell it what are the different urls for the different pages that we want so these are going to be the two urls and all it's going to do is it's going to load a specific component for each url so the way we're going to structure this is when the user navigates to the root url we're going to have a react component and this is a regular react component there's no special componentry needed within react router just makes use of regular react components and we're going to have a component called stockoverviewpage.jsx and so when they navigate to the root path it's just going to load up this component and this component is going to have all of the individual components that make up this page so the way we're going to actually break this down is we're going to have a component for the auto completion and then we're going to have a component for the list of the different stocks and then when the user selects one of these specific stocks it's going to route them to this specific url and this url is going to load up a component called stockdetailpage.jsx and so this component is going to contain the graph as well as the detailed information down here and so that's how we're going to handle client-side routing within our application and you'll see when we get started coding this out it's actually going to be very simple so let's create a new application in replit i'm just going to select the plus button right here and we're going to scroll down and we're going to select react javascript and i'm just going to give this the name of react demo so our projects have been bootstrapped i'm just going to hit run so we can just make sure everything's working and we can see our application was successfully loaded so it looks like everything's working i'm just going to do a little cleanup we don't actually need this text here and in addition to that if we go to our app.css we can either delete this or just comment it out we'll be adding our own styles now for this project we're going to make use of bootstrap just for styling only because i don't want to spend too much time uh having you guys copy all of the css properties and things like that i'd rather just add in a couple of bootstrap properties so that we can have a nice finished polished looking product without having to spend too much time on css so if you go to getbootstrap.com and you just scroll down to include via cdn we want to get just the css only we're not going to be making use of the javascript so we can just copy this to clipboard and if we go back to our application and we can just go to our index.html and inside the heading we can just put this under the title you can just paste that in there we'll save that and then just to make sure that everything's working i'm going to re-add in some text or i'm going to add a h2 tag and just make it say hello or something we'll save that and we should see it in there and i'm just going to add some um classes from the bootstrap library so i'll do class name equals and then i'm just going to say empty dash 2 so this should add or i'll do mt-5 this is going to add in some margin to the top and so we can see it moved down so it looks like bootstrap was successfully loaded and after we get this set up the next thing that we have to do is we have to go to the api that we're going to make use of so we're going to be making use of the finhub stock api this is a free api you will have to register but it is completely free and if you just select get free api it's going to take you to a window where you can register and then once you've registered it'll then provide all of your api keys and so the one you want is this top one right here so you just grab this you can copy it and then just store it in some documentation so you can refer to it later now as i mentioned we're going to be making use of a library called react router so the first thing that we're going to do is we're going to install that so we can set up the routing and so if we select the package manager here and under here we want to search for react router and then more specifically we want react router dom and make sure you get the react router dash dom because there is a react router but that's a different package we want this one specifically here so we'll select react router dom and we can see that it's installing react router dom all right so we'll go back to our files and what i want to do is i'm going to create a new folder in our source directory and i'm going to call this pages so this is going to have the two different pages there's going to be the summary page as well as the detailed page and so i'll create our stock detail page dot jsx and then we'll have our stock overview page as well and so react router dom is going to actually route to one of these two uh components and keep in mind these are just plain react components and so i'm just gonna do export const stock detail page and for now this is just going to return a div that just says this is the stock detail page i'm going to do the same thing for my stock overview page so now that we've got our pages defined i'm going to go back to our app.jsx component and i'm going to import all of the things we need to get react router dom working and so there's going to be three things that we need i'm going to say import and we want browser router we also want routes with an s as well as route singular and we want to import this from react router dom and so we've got these three things i'm going to delete this h2 tag and what i want to do is i want to call browser router and within browser router i want to call in routes and then within here i want to call route so route is going to define the rules right and just to jog our memory and what we want is when the user navigates to the root url so that's going to be just a forward slash we want to load this component the stock overview and when the user navigates to slash detail and then the name of the specific stock so the symbol of that stock we want to go to stock detail page so how do we do that under route we have to provide two things the specific route or path that the user navigates to and then the component should load so for the first one we want to go to the root path so we say path equals and then the specific path so it's just the forward slash and that's going to load up the stock overview component so we have to import that in here first of all so i'll do import stock overview page and this is going to come from the pages folder and then we have stock overview page and to load that component we say element equals and then curly braces and then you provide the component that's going to be stock overview and that's all you have to do and so when the user navigates to this specific path all react router dom does is it loads this component onto the screen that's it react router is actually one of the simplest libraries and that's all it's there to do and we have to set up our next route we'll say route and then we'll say path equal so what's the path for this specific route well we want to do slash detail and then you know whatever symbol now i can't hard code a symbol right because if i say you know msft for microsoft then if they try to check any other company's stock it's not going to work it's only going to match on msft so we need a variable here that can be dynamic and it can be anything the user selects and the way we use variables in react.org is you just do colon and then the name of the variable so i'm going to use symbol but you can call it whatever you want if you want to call it stock you can do that but i'm going to use symbol and it's important to name it something that you can reference because we will need to reference that variable and so when the user navigates to this we want to load a specific element so we'll say element equals and then we just do the same thing and we have to import that component first and then we can just pass that into here and then we'll close off this tag and so now all the routing should be done and if we go back to our components uh we've got everything loaded so let's actually test this out so if i go to the root path which we're already at so the root path is just the forward slash we can see we have stock overview page and what i'm actually going to do is i'm going to open this up in a new tab and this will make it a little bit easier to handle the routing so now if i go to uh if we see the the root path we can see the stock overview component gets loaded and if i go to detail and then just put in some random text it doesn't matter because it's a variable we should see that it should load the stock detail page so our routing is set and everything's good to go and we really won't have to touch too much from the routing side of things because uh we've kind of got all of that said already and so i want to add one quick class so if we go to our app.jsx i just want to wrap this in a container class this is just part of bootstrap everything kind of has to be within a class called container it's going to help with the layouts and once we get that set what i want to do is i want to create a new folder and i'm going to call this component so this is going to contain all of our react components that are not pages themselves so these are just regular react components and if we take a look at the summary page you can see that we have three things we have a logo then we have the autocomplete bar and then we have the table with the list of all of our stocks so the way i'm going to kind of divvy this up is that i'm going to have two total components i'm going to have an autocomplete component and then i'm going to have the table component and so i'm just going to call this autocomplete.jsx and i'm going to call this one stocklist.jsx and so i'll create stock list dot jsx and then the other one is going to be autocomplete dot jsx and i'm just going to copy these components into there just as a baseline and inside our stock overview page i'm going to import both of those components so we can load them onto the screen and then now under this div i can just render out both of those components and we can see that in the stock overview page we've got all three components now or or two components plus the page and so getting started with the stocklist component this is where we get to have a little fun where we can actually finally start working with the finhub api and fetching some data but before we do that we want to store a list of all of the companies or the stocks a user wants to track and we're going to start off by just using the regular use state hook to track that and you'll see that later on in the project we'll actually refactor that and actually make use of the context api so that we can share this data amongst multiple components and so from the react library i'm going to import use state and i'll also go ahead and import use effect because we will have to use that as well and that's going to come from react and i'm going to do use state and then this is going to default to an empty array so uh when you whatever you pass into the use state hook this is going to be the default state so it's going to be an empty list of stocks and then i'll say this equals and then we'll say const and then we'll we'll call this a watch list so it's going to be a list of all the stocks that the user wants to the user wants to watch and then the function that we're going to get to modify this list will be called set watch list okay and so this variable called watchlist is going to return all of the stocks they want to watch and if we ever want to update it we make use of this function and actually instead of defaulting it to an empty array just for development purposes i'm going to hard code a couple of different stocks so that we don't have to manually go in add in a couple and then and then be able to fetch the data that would just require too much work so we'll add in a couple stocks at first as a default and then we'll clear this out once we're done with our project and for now i'll just say maybe the user wants the track of google and we'll say microsoft is the other one and then amazon okay so when the user navigates to this application they'll see data for these three stocks by default and i realized i actually made a mistake um when we actually send the requests to the finn hub api it expects everything to be capitalized so i'm going to change this to be gogl and msft and amzn yeah that actually got me for a little bit i forgot to capitalize it and i think we should actually go to the documentation so if you go back to the fin hub website and select documentation it's going to open up a new tab and it's going to show us how to actually work with the api and the first thing that we have to understand is that from an authentication perspective we have to provide the token as a parameter so we have to say token equals api key for every single request and that has to go in the url or you can add it as a header whichever one you prefer i'm going to go with the first option and the url that we have to send a request to is going to be this https colon slash finhub dot io slash api v1 so all of requests will go to this base url and then we provide a specific path depending on what data we want to retrieve and if we actually go down to the documentation what we want to do is go under stock price and then get quote this is going to be the first endpoint that we're going to access so once again we take the root url and then we go to slash quote and this is going to give us information about a specific stock and it specifically gives us what's the current price what's the change percent change what's the high the low what was the open price as well as the previous close so it's going to give you everything we need for our table and all we have to do is just go to the slash quote endpoint and then we have to do a question mark and then here this is going to be the uh query parameter so everything you see after the question mark is going to be a query parameter so this is kind of providing the api uh specific data that we're looking for so we say symbol equals and then the name of the stock that we want data for and then we want to provide another query parameter and you separate the two with the and sign and then you have to provide the token so for every request we're going to have to add the token and then for the specific quote endpoint we have to provide the symbol so we can just send this as an example and then just update our token and that's going to be the request that we need to send in you can see that the documentation actually pre-fills it with my token so you could just copy this directly from your from your computer and it should work as well so let's work on getting this set up now we can fetch data using the fetch api that comes built in or we can make use of a library like axios and um i prefer to use axios there's no issue with using the standard fetch api but it does make it a little bit easier to work with you know path parameters and query parameters as well so i'm going to install axios and i've actually already got it installed but you can just search for axios and select the first one so this is the one that we want and you can see it's already installed for me so i've already done this so go ahead and do the same thing or if you want you could just do it through the standard method of just doing npm install axios whichever one you prefer now once we got axios installed what i'm going to do is i'm going to create a new folder called apis and this is going to contain all of the files for our api and within this api folder we're going to set up for one for the finnhub api i'm going to call this finhub.js and here we're going to set up axios and so i'm going to import axios from axios and then we're going to do export default because i'm going to export this instance of axios i'm going to say axios dot create so this create method creates a axios instance and here we provide some configuration options and the first one is going to be base url so you do base and you can see it's going to auto complete and you want to make sure that the ur and l are capitalized and here this is going to be the base url for the finn hub api so if we go back to the documentation the base url is going to be from v1 all the way to https so we'll copy that and paste it in here and make sure you don't have the forward slash at the end you want to delete that we just want it to end at v1 so by default when we use axios now or the spinhub.js api it's always going to set this as the base url and then we can add in whatever specific endpoint we want so if we want that slash quote endpoint we could basically just do a plus slash quote and then uh axios will combine them together so that you don't have to retype this entire url out and for now this is going to be all that we need uh we'll make a few changes for uh to this a little bit later but we can go back to our components and go to our stock list component uh we can then oops it looks like i accidentally deleted my use effect hook so now we're going to use a use effect hook so that we can fetch data and i'm going to import my axios so i'll do import binhub from dot dot slash so we're gonna go up a folder api slash and then binhub and so now we'll call the use effect hook and we'll pass in a function and right here we want to specify the dependency array and the dependency array is going to determine when this hook runs if i don't pass a dependency array what's going to happen is this hook is going to run every single time the component renders which would mean we would be fetching data every time it renders and that's not what we want we only want to fetch data when the component mounts so the component mounts we fetch the data that's all and to make it so that it only runs when the component mounts you pass in an empty array and that's it and i'm going to define a function in here called fetch data and this is going to contain all of the logic for fetching that specific quote and i'm going to wrap everything in a try catch block in case we get any errors and in here we can then do finhub dot get and for the url it's just going to be slash quote right because if we go back to the documentation right we just want to do quote and since we already specified the base url it's our it's automatically going to add that and then we want to specify the symbol and then our token of course so i'll say question mark symbol equals and then just we can grab microsoft and then we'll do and and then we'll do token equals and then we'll copy our token and paste it in here and then we will save this to a variable and i'll just call this response and remember this is a asynchronous action so we want to await it and because we're making use of a weight here this function has to be an async function and then down right below that i'm just gonna do a console.log response and then we'll actually call this fetchdata function so that we can actually fetch the data and it looks like there's a typo this has to be a capital h all right and it looks like it did fetch something so let's take a look at the data and if we take a look at the object this is uh what axios return so it shows us the original config which is under config the data is actually going to be the response we get back from the api so that's usually what we're most concerned with and if we go under data you can see we did the closing price the change price the high low so it looks like we were successfully able to get this data and moving forward um we'll i'll probably just show you everything we get back from the api in the console in a separate window just because it allows me to make it a little bit bigger and easier for you guys to read so we can see that the data was shown up here as well all right so that's great uh now we were able to fetch this data however i don't want to have to copy and paste the token into every single request because this isn't going to be the only component that has to get data from the api and i don't want to have to copy this token around all over the place so what we can do is first of all uh what i would prefer to do is go under our apis and here for our axios instance we can already pre-bake our token so i'm going to create a variable i'm going to call this token or key whatever you want to call it i'll call this token and i'm going to paste my token in there and what i can do is i can add in another property called params and then here i'll say token is going to be set to token okay and so now when we send requests i don't actually have to include this token parameter because it's going to come built in with the finhub axios instance and so we could see that it was actually able to get the data again and on top of that the great part about axios is that i can more dynamically add these query parameters without hard coding it into the url by removing this and i can actually just add in an object so i can pass in an object here and i can say params and then i can provide the symbol which is going to be set to microsoft yep and looks like it worked so now once again we got the data from the api server so this is just a different way of configuring axios and i think it's a little bit cleaner and easier because now we don't have to provide the token on every single request and now our request is pretty simple we just have to provide the symbol okay so now that we can fetch data from the api let's save this in some state variable so i'm going to call the use effect hook the use state hook again i'm just going to leave this empty and we're going to store this in a variable and i'll just call this stock so this is going to contain all of our stock data and then we want set stock so we want to manipulate that and so after this console.log i can just do a set stock and then we want to set it to response dot data and the reason why i said response.data is if you take a look at the response remember the response is going to contain the config which is the axios config is going to contain the headers request we just want the data so that's why i said response.data now one thing to keep in mind when fetching data with the use effect hook is there's a possibility that you know after we sent this response out that our component actually got unmounted and so what we don't want to do is end up calling set stock on a component that's already unmounted so how do we prevent that well it's actually very simple what i'm going to do is i'm going to define a variable and i'll say let and i'll just say is mounted this is going to be a boolean and i'm going to say this is set to true so what happens is when the component mounts right this is going to run when it mounts it's going to set mounted to true and then before we do set stock we just do a little check and i say if is mounted is set to true then we can move this up into that if statement that's all and all we have to do is then when the component unmounts we call a return to the use effect hook so this is uh this function that we pass to return is going to run whenever the uh the component gets unmounted so i can say when the component gets unmounted i would just want to set is mounted equals false and so that way when we get a response back and the component got unmounted this check will run and it will not pass and it'll just skip right over it because we don't want to accidentally call set stock on an unmounted component now the next thing that we want to do is now that we're able to fetch some data we want to fetch data for everything in our watch list right now we have three different items and there's a couple of ways of going about doing this the first thing that we can do is i can just take this and just copy it three times and then i can just change the symbol to be the specific uh stock names so we'll have google microsoft and then amazon and i could maybe create a array i'll just say const responses equals empty array and i'll just put a number after these and then we can say responses dot push now do response one and we can just copy this three times and just change this to be response two and then response three and then for set stock instead of sending response that data we could just send the array responses and so let's test that out okay so after i fix that little typo we can see that it printed out all of the responses and i've got the responses for uh this is going to be google the next one is going to be for microsoft and the last is going to be for amazon so we were able to get all three of these however there's a couple things i don't like about this right let's ignore the fact that i'm hard coding all of the different companies because this is going to be a dynamic list that should be changed by the user but what i don't like about this is this is happening sequentially so what happens is we send a request to get the information for google and then once we get the only once we get the information back from google we'll then move on to response 2 and get the data from microsoft once we get the data from microsoft we'll then go and get the data all right this is very slow because we're doing one at a time we're sending one request to the api server and in fact if you go to the chrome developer tools and you go to network and so if you take a look at how long these requests take we can see the first request where we send the request to get google it takes all of this time only once we get the response back can we then go to the second request and then only once we get the response back can we go to the third request so it's doing these things one at a time and that causes this to be a very slow process and if the user wants to see um you know the data for 20 stocks imagine sending each one of those one at a time in series i would prefer to be able to send all of these requests all at once and then the api server just responds them as they come in and that way it should basically take the time it takes to send one request because we're sending all of them concurrently so how do we do that in javascript well what i'm going to do is i'm going to delete all of these or actually instead i'm going to leave those and i'm going to show you guys a tool called promise dot all when you call promise.all you provide a list you provide a list of promises and it's going to try to resolve all of them at once so it's going to send a request for all three of these guys all at once and so i could just copy this config starting from finhub and paste it into here and then just do a comma and then the second one and then finally we'll grab the last response so now i can delete all of these and all we have is this promise.all which has three different promises getting sent to one for google one for microsoft one for amazon and i can delete these and i'll set this to be const promises equals promise that all or actually let me just change this to be responses so we don't have to change anything else and now if i refresh this and it looks like it hit the api limit so i'm going to give it a couple seconds because we have at most 60 requests uh per minute so i'll give it a minute or two and then we'll run the request again and we'll take a look at um how quickly it works now okay so um because of the way react works uh it actually runs that use effect hook twice it basically mounts the component twice so ignore everything from here down what we care about is the first three and notice the the timing of the three requests they all get fired off at the same time and they all roughly complete around the same time so look how much quicker that is versus sending one and then only after that's done we send the next one and then only when that's done we then send so this goes all at once and it basically takes the time of one request because we're sending it all concurrently and so that's all done because of this promises promise.all method so that's great however we're still hard coding all of the companies we don't want to hard code the companies we want to take whatever's in the watch list and then create these dynamically so how exactly do we do that well it's actually pretty easy what we're going to do is we're going to make use of the javascript map method and what our main goal is right we have a list of companies and for each one of these we want to take this string and we want to generate a promise so we want to send a request using this axios instance and we want to do this for each one of these three and so anytime you want to make a change to every item of an array uh you want to make use of the map method i want to show you how that works so here i have this uh this uh array right here with the the three stocks like we had before and let's say that after each stock i just want to add an exclamation so i want to end up with an array where each stock has an exclamation how do i do that well it's pretty easy using the map method i'll say all we have to do is i'll say map i'll say well we call stocks and then we call the map method and what this is going to do is this is going to iterate through every item in the array and so we have to pass a function to tell it what do we want to do and this function gets one argument uh the well actually it gets multiple arguments but we're going to focus on just one which is the element and then we have whatever we want the function to do so what is the element well as we iterate through this array the element is going to be whatever the current item is that we're iterating over so the first time this runs it's going to be an element is going to be set to google the second time this runs the element can be called microsoft and then the third time it runs it's going to be amazon in fact if you want to make this a better name we can call this stock so this represents one of the stocks and then what this function returns is going to be what you want to change it to so we have stock which is going to be set to whichever one we're iterating over so the first time it's going to be equal to google so i'm just going to put this in the comments so this is going to be equal to google or google and what we want to do is we want to add an exclamation rate we want an exclamation like that so all we have to do is just return what do we want to change it to so we want stock plus exclamation that's it or you could do string interpolation and say um stock and then exclamation and so when it iterates through google it'll add the exclamation then when it iterates through microsoft it'll add the exclamation and then when it goes through amazon it'll add the exclamation and then we could set this to a value so i'll say this is my modified stocks because the thing about the map method is that it returns a brand new array and if i do a console.log modified stocks save this and then do a node test.js all right you could take a look at the result it successfully added the exclamation afterwards so we get access to each item as it iterates through it and then whatever we return in the function is going to be entered into the new array and so we're going to do the same exact thing with this but instead of adding an exclamation point we're going to generate a promise or a request to our api by calling the same thing so i'm going to delete all of this instead we could just call our watchlist array i'll say watchlist dot map okay and once again we're going to pass in a function we get access to the stock or the element that we're iterating over and then whatever we return from this function should be a request to our api so i'll say return i will do finhub dot get slash quote and then params and remember we want symbol and we'll set that to be stock because stock represents the symbol that we're currently iterating over and we just pass that in there so now if we test this out and i realized i forgot to do an await now if we take a look at responses we should see that we have now successfully gotten all three of our requests and if we go to our network section we can see that all three of them gets uh got sent out at the same time so that's exactly what we want and so i think we've pretty much done everything we needed to do there if you want to you can set the use state uh hook to be uh by default just an empty array it doesn't really matter however um before we kind of wrap things up and move on to rendering out all of this information uh inside a table if we actually do take a look at this console.log right here which is uh printing out all of the response objects before we uh store it into our state there's something i don't like about this and if we go to our console and we take a look at what the output looks like this is what's getting stored in our component state and if i open up the first one take a look this isn't actually just the data that we get from the api this is the response object from axios so we get the configuration we get the data which definitely what we want we get the headers and the request and most of this information we don't care about why would the component care about the configs of our axios request it doesn't why would it care about the headers it doesn't what about the request it does it the only thing our component cares about is the data i don't want anything else other than just the data so for each of these three items of these three requests i want to go in and extract the data and just delete everything else because we don't want to store unnecessary information in our state so ultimately what i want to do is and i'm just going to create a new file here this is just for demonstration purposes you don't actually have to do this yourself i'm just going to call this demo.js what i ultimately want to do is i want to store in our state for each one of the stocks an object that looks like this so we have the data which is going to contain all of our you know stock data whatever it's called and that's going to come from the data object here and then the next thing i want to do is notice how inside the data it says nothing about what stock this data is for so that's something we have to assign ourselves we can't just extract it from here in fact the information about where the stock is is actually within the config so if we go to the config under params we can see the symbol so inside here we want data to come from data and then we want to whoop data to come from data i'm just going to put this in quotations because the autocomplete's messing it up and then for the symbol this is going to come from config.params.symbol so i want to store this information an object that looks like this so before we save it into our set state i'm going to call the map method to iterate over all of these things and extract an object that looks exactly like this so we are already familiar with the map method so we could just do that again and i'm going to delete this demo.js and we'll go to our stock list and right here before we call set stock i'm going to do a responses dot map and we'll just say this is going to be response and like i said what do we want well we first want to get the data which is going to come from response.data right that's going to be data so the response which is you know in this case the first response we want the data property which is going to return this uh object here and then i want to store information on what is the symbol and that's going to come from the response and i already forgot where it's coming from but i believe it's config params symbol so config params symbol and remember we want to return an object so right now i didn't actually put it in an object so let me create that object and then paste that in here and then we return that object and we'll store it inside a variable called data and then change the set stock to be data and we'll save that we'll go back to here and i'm actually going to print out what our data looks like just to make sure everything looks good and so now we can see that data has just the data that we're looking for and then symbol is set to google so that's exactly what we want now our state looks exactly the way it should so now what we can do is work on rendering out this information inside a table so inside our table for the headers we want one for the name of the stock we're going to have one for the last the change the change percentage the high low open and peak so this is all going to go inside a table element so in our return statement i'm going to remove stock list inside here we'll do a table and i'm going to add a couple classes that come from bootstrap is going to be table hover and then mt-5 so this is just the usual styling for the table this uh we'll make it so that when we hover our over one of the stocks it's going to change the color so we know which one we're hovering over and then this is just going to add a little margin to the top then we want to create our t head right so this is going to contain all of those headers that we just went over and i'm going to add some inline styles which is nothing more than just changing the color and now we'll do tr we'll do th scope equals this is going to be the name and i'm just going to copy this several times all right so now if we take a look we can see we've got our table with the different headers now we can add the actual data and the way we're going to render out this data because remember all of our data right now is stored inside this uh stock state uh is once again we're going to use our favorite map method so i'm going to call uh i'm going to do a curly braces so that we can provide some javascript and we're going to map through this so we'll do stock.map stock data and we want to return and so for the the row it's going to be th and here we're going to provide the stock data dot symbol and for the tr i'm actually going to add in a class this is going to be table dash row and remember because this is react we have to provide a key for each element we return in a list i'll say key equals and this is going to be stock data dot symbol we'll use the symbol as the key and so for this right then we can do td uh the next one's going to be stock data whoops we want stock data dot data dot c next one is going to be stock stockdata.data.d i'm actually just going to copy this a few times next one's going to be dot dp and then we have h l oh and then pc and it looks like i made a little typo here this shouldn't be dot symbol in the curly braces all right and now if we go back to our website when i clear this let's refresh this just make sure there's no errors we could see that we now have our chart and it's automatically going to get updated depending on what is our stock state a couple of final things that i want to do from an aesthetic purpose for our stock list component is that first of all we should color code the change and change percentage value depending on if it um if the stock went up or if the stock went down so we're just basically checking is the change negative okay we want to make it red if it's positive we want to make it green in addition to that um we also want to add in an icon showing the direction uh that it moved so if the stock went down we want the down icon if it went up we want the up icon so those should kind of go hand in hand with the change value so just to kind of hard code something if we go to the this td right here this is for the change and the change percentage if we want to change the color using bootstrap we can do class name equals and then text dash success that'll give us a green color and then if we change the bottom one to be class name equals text dash danger that's going to be the red color so now you can see under the change where we have text success we can see it's green and then when we see text danger it's going to be red so we have to define a function that'll check the value of what direction the stock went and then update this specific class depending on if it was positive or negative and so what i'm going to do is i'm actually going to delete success and danger so for these two we're just going to have it say text dash text dash and then what i want react to do is call a function that's going to contain the logic for determining uh if the stock went up or down and so first of all we're going to provide some javascript and we're going to use template literals and here i'm going to pass in a function that i haven't defined yet called change color and what we should do is we should pass in the stock data.data.d so that's going to determine the direction that the stock went and i'm going to define this function now it's going to be called change color i'm just going to define it right above our use effect hook so it's going to be const change color and then it's going to get in some variable and i'll just call this change and we're just going to use the ternary operator to do a return and we'll say if the change was positive so that means the stock went up we're going to return the text success and if it was not positive so that means it's negative we're going to return danger okay and so now we can see that it's automatically updating the color everything was negative in this case but if we have a positive stock then that should automatically turn green i think our entire stock market's going down so everything's just red at this point we're gonna do the same exact thing for this guy right here i could just copy this and just paste it in and we've got these updating dynamically as well next thing that we have to do is add the icons and i'm going to make use of a library and so we'll go to the package here and and we'll install a package called react dash icons and this is the one we want right here so i'll add this so for this library if we take a look at the documentation we can see that it supports icons from several different um you know frameworks uh we since we're using bootstrap we might as well just stick to bootstrap icons and the way that it works is that all you have to do is you do import the icon name and then you do react dash icon bs for bootstrap and all we have to do is then find our specific icons so it's going to be this one right here bs fill carrot downfill and if i search for carrot we should also be able to find the up one so bs fill carrot upfill as well and so if you just select this it's going to copy it into our clipboard which is awesome and now if we go to the top of our file i'm going to do import paste that in from react dash icons slash bs and this is just a regular component now so i can go down here and after this i can just put in another component all right and now you can see that you can see that the component is right there next to it so that's all we have to do however we have to select the right icon depending on what direction it's going and so what we're going to do is we're going to set up another function just like this change color function i'm going to create a render icon function that's going to do essentially the same thing so here i'm going to delete this and in here we'll pass in our function render icon and we'll pass in the same information which is going to be stock data dot data dot d and then i'm going to define our function const render icon get access to the change again and we're gonna do the same thing change greater than zero we're going to return and actually have to import the other one as well so we want the up carrot up fill and if it goes down then we're going to return the other one and i can copy this and paste it into this one as well now if we take a look we could see that all of them have an icon so i think that's a good stopping point on the stock list component there's still a couple more features we're going to have to add to it but i want to take a break from it for now and i want to move on to the autocomplete component and just to remind you guys what this component does it's going to be a simple input field where the user can search for available stocks so if the user wants to find you know tesla you'll just start typing in the letters tsla and you'll see that it should be able to search through that and it's an autocomplete so if you actually go slow enough and i just type in ts it's going to find all of the companies that start with ts and then i can just keep adding another letter and then it's going to keep narrowing down the field until we get to what we're looking for and then from there we can then select the company and then it's going to get added to the list and i want you to take a look at the network request right the for each letter they type it's going to automatically send a request back to the api so for the headers you can see that uh in this case the query it just has the letter t and the next one has the s l a so we send a request for every letter and you know we can obviously customize this so we don't send it for every single letter the user types however i wanted to keep this component as simple as possible so let's tackle creating this component and so we'll go to our autocomplete.jsx and within here in this parent div i'm going to add in a couple of class names uh it's going to be the width is going to be set to 50 i'm going to add some padding i'm going to give make it rounded and then the margin is going to be auto so it centers and within this div we'll now add our input actually before we add our input i'm going to add another div i'm going to give it a couple classes so it's going to be form dash floating and then drop-down and within this div we'll then add our input and for the input we're going to add some inline styles mainly just the background color i'm going to give this an id of search type is going to be text and i give this a class name of form control this is coming from the bootstrap library and i'll also give it a placeholder of search and if we just take a peek at what this looks like that's pretty much what i want it to look like and for my autocomplete i'm going to disable the built-in autocomplete and then under the input i'm going to add a label we'll do html4 this is going to point to search so this is going to match up with the id of this input field and the label is going to say search all right and just to double check let's just take a look all right everything looks good now the next thing is we want the drop down so how do we make the drop down well there's all this is going to be pretty easy with the bootstrap library for the drop down under the label we can create a ul so i mean we can really render anything in the drop down and then i'm just going to add a couple of items i'll just say stock one two and three and for this ul we're gonna add in some class names mainly drop down dash menu and that's all we really have to do so this is our drop down and i'm going to actually go back to my browser for a second okay so you'll see that right now there's no drop down however if i inspect this and go to elements we can inspect this and then go down you can see that the drop down is there it's just right now at the moment if we go to computed we can see that the display is going to be set to none right now the drop down menu is set to display none so you don't see it so it's still actually on there but it's just being hidden and that's because when you assign drop down dash menu from the bootstrap library it's automatically going to give it a display of none and if you want to show it using the bootstrap library we have to add in a class called show and so now the drop down actually shows so this simple class is what is what's going to determine if we show the drop down or not so this is something to keep in mind and make sure you keep that on the top of your head when we're implementing the logic of you know rendering out all of the data once we start searching for it the next thing that we have to do is we have to make this a controlled input and this is going to be like with any other standard input in react so i'm going to import the ustade hook and to make this work i'm going to create a variable called search and set search so this is going to represent whatever the user is trying to search and i'll do use date and default is going to be an empty state and then in my input field we're going to set the value of the input to be set to search and then we're going to set a on change parameter whenever the user types in something and i'm going to say we're going to pass in a function and we're going to say that set search set that to be the value of e.target.value okay so what we're doing here is i'm saying that whenever the user types in you know a letter it's going to trigger this on change which is saying uh get the value of that of the letter that we just changed or whatever is our input field and set that to the set search function so that we can update our state and then the value of our input will be synced to whatever our state is so that's how we make this a controlled input and we can see everything types out just fine and if we can actually go back to the browser type here and go to my redux dev tools extension and go to the autocomplete we should see that the state should match up with whatever's typed okay looks like everything's good and now the next thing that we want to do is implement the fetching data logic so i'm going to import the use effect hook and then we're going to call the use effect hook and we'll do the same thing that we did before we'll pass an error function and before we get started sending a request or implementing the logic let's go back to the documentation and take a look at what endpoint we need for searching and the one we want is under stock fundamentals and under symbol lookup so you send a get request that's going to be the method and you send it to the slash search endpoint and you provide one query parameter which is the letter q and then whatever text the user searches for and then this is what one of the results are going to look like so it's going to include the you know the type symbol display symbol and then the description and so that looks simple enough so once again i'll do we'll define a function called fetch data we'll put in our try catch block and then below this we'll call fetch data and let's import our api our finnhub api and now we can do a const response equals and then we'll do binhub.get the endpoint is going to be the search endpoint and then params well this is going to be set to this queue and that will be set to the value of whatever the user searches we just say search and this is an asynchronous operation so we'll do a wait and then i'll do a console.log of response so let's take a look at that and so right away even though we haven't typed anything it looks like it's fired something and if i take a look at the config and get this is going to let's see where's the params yep params right here we could see that we're sending it with a empty search and when it sends an empty search to the api it returns everything so we got an array with 11 000 results so that's obviously not something what that we want and so right there what i think we should do is um we should first run a check and say that only if search dot length is greater than zero so if there's only if there's at least one letter that the user has searched then we call fetch data okay so let's reload this and so these these first results are just from this table um but we can see that we didn't actually uh search anything it didn't actually try to send a request to the search api so let's try um sending one letter and we can see that it did in fact send a request and we could see that the results as a whole bunch of stocks are companies with the letter a in it let's add another letter and this time if we take a look at the config we can see that the search is a n and the data we know we now have 28 results we do the letter e now we should see that we now have 29 results and let's try one more letter and we can see that we have 25 results okay so it looks like it's working um but one thing that is happening with the use effect hook is that right now since there's no dependency array it's going to run every single time every single time the component re-renders and we don't necessarily want that we only want this to run anytime the search changes right because why else would we want this to run it's all we only want to send a request whenever the user has changed the search either added a letter deleted a letter or made some change or pasted something in so what we can do is under the dependency array you just say search so now this use effect hook will only run when search changes the next thing that we have to do is we have to store the results someplace the results from the api so i'm going to use the use state hook again and i'm going to call this a results and down here what we're going to do is i'm going to set results to be results dot data sorry response.data and once again just like the previous component that we worked with with the stock list we also want to do this is mounted trick where we make sure that the component is still mounted and so we also have to perform the return operation where we set that to be false so i'll copy this and we just do a check here is mounted okay so let's uh let me go to my redux or my react dev tools again i'm going to go to my autocomplete component and we're just going to take a look at the state so if i type in the letter a we could see that the state was now set and it looks like the way that the object was set it's a it's returning a count and a result i just want the result i don't want the count in there as well so i'm going to do response.data dot result let's try this again a okay we've got the results that's exactly what i want let's see if it updates right now there's 42 now there's 24 perfect now let me change that to an a we get 42 again and then if i set it back down to zero what do you think is going to happen so after i search something notice how the state doesn't get cleared out the state still has that a search result so what's happening here well if we go back to our code you can see here if it says that if search dot length is greater than zero we'll fetch data and in fetch data we set the results however what happens if we have a length of zero a length of one and then go back down to zero so we delete a letter well at no point are we updating set results to be back to an empty array so what we have to do is just put an else statement here and just say set results to an empty array and so that way if i type in the letter a i'll get 42 results again and then when i delete it it's going to hit that else statement and then it's going to remove all the entries and i'm going to delete the unnecessary console.logs okay so we've got all the data fetching logic implemented now we have to just show the drop down and so how do we do that remember i talked about how all we have to do to show the drop down is add this class called show and then it's going to show this drop down so what i want to do is uh implement a function that's going to figure out if if search has or if results is not empty then i want to add the show class if results is empty then i don't want to show it so i'm going to define a function called um render drop down so this function is actually going to be responsible for rendering this ul so i'm actually going to uh comment this out for now that didn't work and i'm going to put in a little logic i'm going to say drop down class equals and then we check if search is a true value so if search has um you know any text in it then it's going to return true if search is an empty string then it's going to return false so if it's true and there's some search in there then we're going to return the class show because that's what shows the drop down if not we're going to return null and then the rest of this class is going to be responsible for returning that ul so it's going to render out that ul and for class name what i can do is add a little trickery and i can say drop down dash menu and then i pass in drop down class so it's going to add in show if we have some sort of search result and for now i'm going to hard code some lis again okay so i type in a letter and i realized we have to actually go down here and call that function render render drop down so if i type in a you can see that now since there's a search result it renders out the drop down if i delete it it goes away so that seems to be working now all that we have to do is we have to take the results that we have and render out that information so we'll go to our render drop down we'll just delete these lis and once again we're gonna do our favorite map method so i will say results.map we have our li let me add in a class name of drop down dash item and then what i want is we have two values there's going to be result.description and then result dot symbol so i want the company name and then followed by the result uh of the symbol of the company and i actually want that wrapped in parentheses so i'll do parentheses let's try this again all right look at that so i got the company name followed by the ticker and we can see this is a massive list and what i want to do is i want to implement some scrolling and i want to hard code the height of this uh of this drop down so it's not going all the way down like that i don't like the way that looks and to change that under the ul we're going to add in some inline styles the first thing is going to be the height i'm going to set this to be 500 pixels overflow y so this is going to set this to be scroll uh overflow x i want to i want to hide the scroll bar in the x direction and i also want to add change the cursor to be a pointer so the user is aware that he can select one of them let's try this again that looks much better you can see we can scroll through the results and one other thing is that since we're rendering out a list of items just like with any other list in react we have to provide a key so i'm going to set the key to be the symbol again so we'll say result dot symbol so now that we've set up the autocomplete functionality the next thing that we want to do is after a user searches for a list of companies once they find the company that they want to add to their list they should be able to select it and then it should show up on this list so we should set up a on click event handler so that when they click on a specific li it should then add it to the list of stocks that the user watches now the problem with this is that the list of stocks that a user wants to watch is currently in the stock list component under the watch list state so our autocomplete component does not have access to the state of the stock list component so we're in a little bit of a pickle and i've set up a powerpoint just to kind of quickly show what the issue is and how we can tackle the the issue and some of the different solutions that we have at hand in the stock summary page we have basically three components we have the stock summary page component itself which is responsible for rendering out the stock list component and the autocomplete component and the stock list component has the list of stocks the user wants to watch that he's storing in a use state hook and the variable's called watchlist and the problem with this is that unfortunately the autocomplete component does not have access to the watch list so when the autocomplete component wants to add something to the watch list at the moment he cannot do that so we have a couple of different options the simplest solution to this is to lift the state of this watchless state up a component specifically up to the stock summary page that is a parent component to both of these components and then what we can do is then we can pass that information down um as props to stockless and autocomplete and that would work just fine however what i want to do is i want to make use of the context api i think this is good for learning purposes and you can take a look at how we can create global state using the context api and the way that the context api works is actually very simple what's going to happen is we're going to create a component called a provider component and this is really fundamentally just a regular react component that wraps your entire application and so by wrapping your entire application in this provider component what it does is it allows individual components to access its state so we can move the watchlist state up to the provider component and then the stock list and the autocomplete components can then query the state and get access to that state directly and any other components in our application can access it directly without having to pass it down as props so that's what we're gonna do moving forward we're gonna implement a a context to store our watch list and give us functions uh that'll manipulate being able to add and remove items from our watch list so let's go ahead and implement our context i'm going to create a new folder in our source directory called context this is going to store all of our context we just have one for this project i'm going to call this watchlist context dot jsx and to create a context we're going to import create context from the react library so i'll do import create context from react and then to actually create the context all we have to do is export cons i'm exporting it because we're going to have to import it in another file and then just provide the name of your context so i'm going to call this watch list context and then we call create context and we have now successfully created a context after we create the context what we have to do is we now have to create that special provider component to wrap our application in that provider's component that provider component is responsible for passing data down to any components that's interested in receiving that data and to create this component it's just a regular react component almost 100 identical we just do export const and then i'm going to call this watchlist context provider you can call this component anything you want but i usually just like to grab the name of the context and then add the word provider afterwards and then we'll pass in the props and then we have to return and this is the only difference so we're going to return a special component called watch list context so we're grabbing the context right and from there we can grab something called a provider component and that's all you got to do and this needs the dot provider as well okay and so what we can do now is we can take this provider component and wrap our entire application and our application can have access to any data they want and when i say any data at once it means what i mean is any data within this component because like i said this component is just a regular react component that can make use of the use date hook the use effect hook any other hooks that you want and so the stock list has access to the watch list and i want to make this watch list accessible to all components what i'm going to do is i'm actually just going to take this from here remove it from here and i'm going to move this exact use state hook into my context because remember my provider component is just a regular react component so i can just paste that in there and i can now manage my watch list within my provider so how do i actually pass this data down to my other components well inside this component here i have a value prop and here i can pass down whatever i want so if i want to pass down watch list i can and this is perfectly fine but i'm going to in the future pass down a few other pieces of information so the data that i want to pass down in the value prop i actually want it to be an object and this is just an example of what i want it to look like it should be an object obviously watchlist should get passed down and i will also have an extra function to add a stock to the list to the watch list as well as delete a stock from the watch list as well so that's what i wanted to look like so what i'm going to do is i'm going to remove this instead of just passing watch list i'm going to pass down an object because i want an object and right now i just have a watch list but we'll implement the logic for those other things in a second and i'll remove this so our context and our provider component are done we now have to take our provider component and wrap our entire application so if we go to myapp.jsx and it looks like it already got imported but i'll just type that in real quick for you so it's going to be import watch list context provider we want the provider not the context from context watch list context and now we have to take this special component and wrap our entire application so technically you don't actually have to wrap your entire application you just wrap it in whatever subset of components should have access to that provider so i'm just going to wrap my entire application just to keep it simple and i'm going to call my watch list context provider and i take the bottom one and then just move it under browser router so now if you actually take a look at our application our actual application is this and all of these components within this watchlist context provider have access to that value prop that we're passing down and i'm it's it's throwing an error and that's just because i'm using this use state hook but i never imported it so we'll import it okay so everything's done no errors but interestingly enough nothing is being rendered onto our screen what's happening well we know that we changed the watchlist context provider and we added in here so that's obviously breaking it but let's understand why it's breaking so notice how our application starting from browser router is now being passed into our watchlist context provider as a child prop right it's no different than you know if i had like a an h2 and then i'm providing you know some text right some text is a child prop i'm passing it in between the tags so if i go to my context provider take a look at what we're rendering we get the props but we're not doing anything with it right we just have our context provider and that's it so we have to tell our context provider hey let's render all of our child props normally like they should be so all we do is just do props dot children so this is going to render all of the context between our provider tags okay and now if you take a look everything is working as it should if we take a look at our app it's working and more importantly if i go to my watchlist context provider in my react dev tools we can see that our state is being there and is working and we can see that everything looks to be good and now our next task is going to be how can we make it so our components have access to the state within our provider okay so now to make it so our stock list component actually grabs the watch list from our um from our context instead of storing this himself we're gonna actually remove this i'm gonna delete this it's gonna break our application that's okay and to retrieve the data being passed down in this value prop what we have to do is we have to make use of a specific hook called use context so i'm going to import use context and then we just say use context and then we have to pass in the a reference to the actual context which is watchlist context so we have to import that as well i'll say import watch list context remember this is the context not the provider okay and then we store this in a variable you know const value but that's going to return this entire value prop if you want we can just do a console.log a value and if we take a look you can see that we get access to an object with the watch list so that's perfect that's all we have to do to get access to anything passed down from a provider now we don't need access to the entire value we just want access to watch list at the moment so i'm going to destructure out watch list and now our app is going to work exactly as it should and i need to remove that console.log all right perfect so now we can actually go back into the autocomplete component and implement the logic for adding a new stock but what i want to do is i don't want to store that logic within the autocomplete component i want to store that in my context and i want the context to pass down a function so that the only thing the autocomplete component has to know what to do is just call that function so let's go back to our context and i'm going to define a couple of functions so the first one is going to be add stock how do we add a stock to our watch list so this is going to be function and this function the autocomplete component is going to pass the name or the symbol of the stock and all we have to do is say if or and all we have to do is just say set watch list and then we spread the current so we copy over the current watch list and then we add in the new one and the new stock and that's it however this is going to create one issue and that is that what happens if we try to add a stock that's already in this list right let's see google's already in there and then the user searches google and then tries to add it well now we're going to end up with two googles and that would look stupid in our application we don't want to have the same stock listed twice so we have to perform a check to make sure that the stock that's passed into this function doesn't already exist in the watch list easiest way to do that we could just do an if statement and just say watch list and then we call the index of and then we pass in the stock and if this equals equals equals negative one that means it's not currently in that list so only if it's not in the list will we add it in and so that's all the logic for adding a stock let's now implement the logic for deleting a stock and to delete a specific stock from a list we can call watchlist dot filter and this is going to iterate over the array and we'll get access to the specific element it's iterating over and we'll just say we want to return if element does not equal equal stock so that means it's going to go through the list in our current watch list and it's going to find all of the entries that do not match the stock that's passed into this function and if they do not match then we will keep it but if they do match we'll delete it that's all and then this is going to return a new array and so all we have to do is just then call set watchlist and then pass the result of that into set watch list and then we're going to pass these down so i'll do add stock and delete stock so now that we have the functionality for adding stock i'm going to go to our autocomplete component and actually it looks like i have an error hold on let me yeah i'm not sure what happened there but i just saved this file again and seems to fix the issue so it doesn't look like there's anything wrong but let's go to our autocomplete component and let's set up that uh use context hook i'm going to say const which i'll just say use context and this is going to be the watch list context and let's just copy the imports from the other one so i'm going to copy this and then we'll import use context and then what do we want we just want to destructure out the add stock and once we get that what we want to do is on the specific li for the result we're going to set up a on click event handler and here we're going to pass an anonymous function that's going to call ad stock and we're going to pass in the result.symbol so this is just when the user clicks on one of the results it's um let me find an actual stock uh when it clicks on this it's going to pass the symbol of that specific company to the add stock function that we get from the use context which will then go to the use context and then i'll add it to the list so i'm going to go to inet we'll search that and then we'll click on this okay and this thing still stays open but that's okay we'll fix that and i don't think it actually worked so let me actually go back to the website okay so let me try this again okay so it looks like there's some sort of issue let's go back to my autocomplete and figure out what i did wrong i did an on click we call ad stock and it looks like i figured out the issue so what's happening here is that when i select anet it is technically getting added to the watch list and i can actually see that by going to my react dev tools and going to my watchlist context provider we can see anec got added but the problem is is that once it gets added if we go to our watch list context sorry our stock list component so this is the component that renders out the table it runs this use effect hook and this use effect hook is responsible for getting the quotes of all of the items that are in the watch list however if you take a look at when this use effect hook runs it only runs when the component mounts so after it mounts it does not matter how many items we add to the watch list it's never going to run again so we want this to run every time watch list changes so all we have to do is just pass that into the dependency so we'll just pass in watch list and so now anytime watch list gets updated a stock will get added and we can see that it already got added in there so that's why it wasn't getting updated so i'm going to refresh this and we'll test this out again so i'll type in a net select it there we go it gets added in perfect now i do want the drop down menu to go away after i select an item so i'll go back to my autocomplete and this on click event handler i'm going to actually remove this shorthand notation i'm going to add in two steps so it'll be add stock again result dot symbol and then afterwards what we want to do is we want to clear out the search and when we clear out the search it'll automatically remove the drop down so i'll say search set search so we're calling that hook right here and we're gonna set the search for our input to be empty and when it's empty the drop down will lose or it'll get the uh extra it'll lose the show class which means it'll be hidden from there on out so let's try this again i'm going to save this select this and we can see the drop down goes away so the last thing that we have to implement from the summary page is the delete functionality so we're removing an item from the list however there's something i want to show you guys when it comes to event propagating within react and the only way for me to show you guys the issue would be to first implement the detail page so we're actually going to take a break from the summary page we're going to the last thing of removing the item we're going to cover that at the end of the project instead i want to move on to the detail page and just to kind of reiterate how this is supposed to work when i select on a stock when i select in a row take a look at the path right now it's the root path i select this it then goes to detail then the name of the stock and then it loads up the detailed page so let's implement that this is going to be done through react router and you'll see that it's actually pretty easy and we made use of the apex charts library to build out the charts and you'll see that it'll actually be dead simple doing that as well so let's go back to our app and let's go to our stock list component and let's find our uh our specific row so when a user clicks on a row we want to call an on click event handler and right now i'm just going to have this call a function and this function is going to be called handle stock select so let's define this function and what we want to do is when we select a specific row we want to tell react router which is our routing library to route to a url of slash detail slash stock name how do we do that well react router comes with a built-in hook that makes it very easy so let's import this hook from react router we'll do import use navigate from react dash router dom and now we'll just do a const navigate equals use navigate okay and so now if we want to go to another path or url we just use this navigate object so i'll say navigate and then all i have to do is just pass in the url that we want to for the user to so we want to go to detail slash and then the stock name so we have to get the stock name so we'll say that um the event handler has to accept it as an argument so we'll say um symbol so the symbol of the stock and then we can just do string interpolation and then just pass in symbol so now when we actually call this when it gets selected we have to pass in the symbol so where is the symbol it's stock data dot symbol i'm just copying what's here and that should be all we have to do actually so let's go take a look okay so if we take a look at the url right now we can see it's at the root url so this is the equivalent of just a forward slash and so i'm going to select google and we can see that it routes to slash detail google and we can see the stock detail page so everything is working exactly the way we expect it however one thing is um i want to be able to get the clicker icon instead of the regular pointer because i want to give the user a little bit more feedback and we can easily do that by passing an inline style and i can just say cursor is set to pointer now can see that we get a pointer perfect okay so let's go to our stock detail page now in our stock detail page the page has to be aware of the specific url because the symbol or the the stock that we want to see detail is in the url so how do we extract that information from the specific url like how do we get it how do we get this value from the url well once again we're going to make use of the react router library and we're going to use a hook called use params so let me import that so now i'll just do const x equals use params so this will get all of the parameters however we don't want all of them i just want the symbol right and that parameter where that comes from the name is going to come from our original route so whatever we passed here where it says detail and then the variable this parameter we can just extract out symbol so here i can destructure out symbol and let's render out stock detail page and then let's just render out the symbol to see if we can actually get that information so now if i select google we can see stock detail page google so we were able to get that parameter for the stock detail page what i'm going to do is i'm actually going to fetch the data within the stock detail page component and then i'm going to pass that data down to the chart component i want to keep the chart component as simple as possible i just want the chart component to be responsible for rendering out the data i don't want it to be responsible for fetching the data so i'm going to have the page actually fetch this information so to do that we're going to make use of the use effect hook again and i'll define my function for fetching data and let's import axios so i'm just going to copy the import from another file well actually i might as well just type it out now we can do a const response equals and then we can fetch our data but we have to find out what data point do we actually want to fetch or what which endpoint do we want to fetch so if we go under stock price you want to go under candles so this is going to return historical data and to get the information you send a request to stock slash candle and then the parameters are going to be first of all the symbol like you would expect then the resolution so what's the resolution if we go down here resolution is going to be what is the gap between each data point that we want to plot so this is um every minute so we'll get a data point for every single minute every five minutes 15 minutes 30 minutes 60 minutes uh one data point per day one per week one per month so if we're going to chart out um you know one day's worth of history we may want to do every five minutes or every minute however if we're going to chart out one year worth of historical data you don't want to do every minute that's too many data points i would instead prefer either every day or even every week so that's what the resolution is then from and to so from is going to be you know what is the earliest time that we should get a data point from and two should be what should be the last data point time stamp from i worded that incorrectly that should be the last time that we should grab a data point from so if we want um one day's worth of historical data the from would be the unix time stamp for exactly 24 hours ago and then the two would be the current time and then if it's a year then the from would be moved back a year and so on so let's go back here and i'll do a weight binhub.get and this is going to be stock candle and then params well we we're gonna pass in the symbol then we need the from the to and the resolution okay so how do we get this information well we're gonna make use of the date object so i'm going to go and say const date equals new date so that's going to get the current date and if or if i want to get the current timestamp i'll do uh const current time equals date dot get time so at that point we can take the current time and pass it into the two because that's the last data point because we want the the current time to however the api i found out and this took me a a quite amount of time quite a bit of time trying to figure this out but this get time returns it in milliseconds the api expects it in seconds so to convert this to seconds what we want to do is we want to divide it by a thousand so that's going to give us seconds and then we also want to do a math dot floor so that's just going to truncate any extra decimals and in fact i think it might actually help if i just kind of lab this up real quick so we'll say const date equals a new date and then if i do a const current time equals date dot get time and if we run node test.js and i should have console logged it now if i run this this is going to be the unix timestamp for the current time in milliseconds if we want to convert it to seconds current time seconds and then we do a console log so you can see that this is now being represented in seconds let's just move the decimal over three places so that's really all that's doing and if we ever want to get like if we want to go get the timestamp for one day ago how would we do that well we can take the current time in seconds so i'll say current time in seconds and we want to subtract 24 hours right that's one day so how do we get to 24 hours well this number is in seconds so we have one second how many seconds are in a minute we have 60 seconds in a minute we have 60 minutes in an hour and we have 24 hours in a day and so this is going to be we'll call this one one day ago so this is going to give us the time for one day ago um how would we do one week ago well we can do which is going to be current time in seconds minus this represents one day we already know that and then we just multiply it by seven because a week is seven days and then what's a year it's going to be a year is just going to be 365. so that's all we got to do to get the to and from time so we have the current time let's get the time for one day ago so i'll say const one day equals current time minus 24 times 60 times 60. and so the from is going to be one day so from one day ago to the current time so the two is going to be current time and then the resolution we can do every 30 minutes and now let's fetch this data and we actually want to do this only when the component mounts so fetch data and then we'll console.log the response okay so if we take a look at the response something interesting is happening it says that data under data it says no data so i'm not really sure what's going on but as a test i'm going to change this to be three days ago and i want to see if this fixes the issue and now if i take a look at the data oh look we get some data back so for some reason if i do one day ago nothing happens but if i could do three days ago something happens and i actually noticed this when i was laughing this out and i only noticed this issue right before i started to record and that is that i'm recording on the weekend this is a saturday well technically it's sunday now um and the stock market's closed on sundays so there's no actual data points for one day ago because if you're on if it's sunday one day ago saturday you're not going to get any data points so this is something to keep in mind so we have to fetch data and get calculate the time uh depending on what is the current day so if i want to get basically just one day's worth of uh of data so if i want to get friday's data well if it's saturday i have to go two days back and if it's sunday i have to go three days back that's all so i have to put in a couple of if statements uh when capturing the time this is just one of the uh kind of the pain points of working with with this kind of data um i didn't even think about this issue when i first coded it out so all we have to do is do an if statement and i'll say if and then we grab date dot get day so this is going to return a number depending on what day it is and saturday it'll return a 6. so i'll do equals equals equals 6. so if this is a saturday then i'm going to make one day first of all is going to be a variable that i can change so it's going to be let if it's saturday then i'm going to do get two days worth of data so i can get friday's data and then i'll copy this and then if it's sunday which is going to be a zero then i want three days worth of data so now our application's smart enough to figure out that hey if it's saturday we're to have to get two days worth of data if it's sunday it's going to be three days worth of data and then if it's not any one of these days and actually this should be in if else i'll say if and let me move that up and then finally else one day is just going to be just one day so we'll remove the three okay so back to our application and now we've got some data so to understand what how this data works is pretty simple so t stands for timestamp so at this specific time this is a unix time and if you ever want to convert this pretty easily there's a lot of tools online like this epoc converter.com you just take the time you paste it in there and then it tells us hey this is uh this is the timestamp of that data point so this is august 25th at 8am so this is the timestamp and then these are the values that we saw before at that specific timestamp so what was the close what was the high what was the low what was the open and what was the the volume i guess so now that we've got this data let's also get the data for one month sorry one week and one year and i'm going to define a variable so i'll call this const one week which equals current time minus 7 times 24 times 60 times 60 and then for one year we'll just change this to 365 and then we can just copy this and we'll change the from to be one week and the resolution to be and we'll just call this response week response day and the resolution can be you know every hour so we just need a data point every hour and then we have response year it's gonna be one year resolution can be i don't know you know every week that would give us 52 data points if you wanted every day you could do every i think it's every day what was the yeah d stands for day so it just depends how detailed you want it to be i'm just going to do one week just because there's no need to grab 365 data points for this demo so this is going to fire off three requests get all that information and then i can just do a console.log of all of these okay and so now we've got uh this is going to be the day this is going to be the year of the week and then this is going to be the year however if you've noticed that this is all happening in series sequentially so this one has to complete first then we send the request for this and then we send the request for this and we can confirm this by going to our network tab and there's a lot of networks so let me actually clear this refresh so notice how one i hated that one complete one one completes then the next one completes and then the next one completes so we don't want that so we're going to do the same thing that we did for the um stock list component where instead of fetching it one by one we do the promise.all method so we could just fire off all those requests at once so here i'm gonna go up here and i'm gonna do const responses equals await promise.all and then we provide a list and i can just copy these into there and then we can just do a console.log responses all right and we see all three fired at once perfect perfect perfect and i think something's actually erroring out hold on let me see if i can find this out so let me put this in a try catch block which we should have done anyways okay never mind okay all of them are in there that's good everything's working now the next thing that i want to do is i want to format the data because if we take a look at the data this is not exactly in the most convenient format because this is still the axios response so it's got all of the extra config information that i don't care about it's got the headers the request i don't care about that i want the data but in addition to wanting the data i also want to format it a little bit differently and the format that i actually need this in is going to be a little unusual but you can see right now we have a object and then for the closing value it's a list of all the values and then for the t is going to be a list with all those values and so the first item in here matches up with the first item here with the time step here the second one second one and so on and instead of doing it like that i need it in a specific format for my chart and i want the data to look like this so i'll say constant data and it should be an object with an x value of the t value of the t right that's going to be you know this here and then the y should be the closing value so what was the closing value at that time and then i want a list of these so it would actually be a list and then i would have a couple of these so that's that's what i want the data to look like so we're going to have to transform this data ourselves and let's define a use state hook so that we can save our data so i'll say const we'll call this chart data and then we have set chart data equals use state and i showed you what we wanted the the data to look like and i'm actually going to save that in a file actually don't worry about that and actually what i want to do is i want to store in our um in our in our hook in our chart data i want to store it like this so in our cons chart data it should look like this we should have an object with a property of day and this is going to have data for one day and then we'll have a week and then we'll have a year of data for a week data for year so that way our chart can just pick whichever one it wants and then the date the data for each one of these should be the way i showed you guys so that was the data equals object that's going to be a list an array with uh multiple objects with an x of some value and a t and a y of some value and there's going to be multiple data points so that's what i want the data to look like so this is going to go in the value here so hopefully this makes sense this is kind of the most confusing part is just manipulating the data for the chart but i want to get it into that format so down here after we fetch the data i'm going to call set chart data and we're going to pass in the object with the day property with the week property and the year property and we're going to call a function which we're going to define in a bit format data and here remember the responses for the responses the first one is going to be for the day the second one is for the week and the last ones for the year so i could say responses and then we want to grab zero so the first entry and then within the zero we want just the data right we only care about the data we don't care about the configs so i'll say data we're going to do the same thing for the rest of these guys and then this is going to be 1 is going to be 2. so let's now define this uh function outside of our component we don't really need it in the component so it's going to receive some data which is going to be an array and guess what we're going to do we're going to do uh the map method so say data dot and so right now we're getting this data object right here so we want data dot and then we want to iterate over t t dot map and we'll get access to two things now you know normally when we did the map method we get access to just one which is the element that we're iterating over but we can actually get another value which is going to be the index of the item that we're iterating over so i'll grab the index and so i'll say return so x is going to be the element so that's going to be the specific time stamp right so this could be this time stamp but we have to multiply it by a thousand because uh the the api does it in seconds and unfortunately our chart does it in milliseconds so just multiply by a thousand and then we have to get the corresponding y value right so for the first item in the t array we want the first item for the c array so we just say whatever index we're on just grab the same one from c i'll say y data dot c index and that's all we have to do and let's refresh this responses is not defined let's take a look at where that is oh yeah that's silly me so we're going to move this into our try catch block now if i go into my react component extension and we go into stock detail page and we take a look at our state our state looks exactly the way we expect it to look so we've got one for day with x y we've got one for week with the x y coordinates and then the y and then the year perfect and for the dependency array um technically this will work the way it is however if the symbol changes we should run the use effect hook again so we're going to add this to the dependency array and for returning data uh we're going to do a couple things first of all let's create our chart component so i'm going to call this add file we'll call this stockchart dot jsx and i'll say export const chart and then in our stock detail page under this div i'm going to actually do two things so first of all we don't want our chart to render until we have our chart data set so if it's still fetching data we don't want to render the chart because there's nothing to render so i'm going to say if chart data and then i'm going to do and and and render out a div and then within our div i can call my stock chart component and we'll import our stock chart component and so what exactly is happening here this is a nice way of saying if chart data is not null then i want you to render out this data if it's not if chart data is null then it's going to return null and it's going to render nothing so it's basically just doing a little if statement if chart data is a value we'll render this out if it's not then nothing will get rendered out so let's test this out no errors and you can see it loads up there's nothing there and then stock chart comes up after we get chart data perfect okay so let's work on our stock chart component the first thing is we're going to receive some props and mainly it's going to be the chart data so i'm going to destructure that out and then when i actually call this in my stock detail page we're going to have to pass in that data so i'll do stock chart then chart data equals chart data and i think we should also pass down the symbol because the chart should know that as well so i'll pass down the symbol and now in our stock chart what we can do is we can destructure out the day week and year from the chart data and now it's just a matter of configuring the specific chart library so we're going to make use of a charting library called apex charts so let's go to the documentation in here and so all we have to do is do an npm install apex charts so we can go back and i'll go here and i'll search for apex charts and we want that first result and in addition to that if we go down to integrations they have react integrations that make it a little bit easier to work with the charts and so we have to install a second library which is kind of like a wrapper for the apex charts library to work with react so that we don't have to do all of the hard work ourselves so this is just called react apex charts and i will install that as well and if we take a look at the react integration all we have to do to create a chart is just pass in the chart component that comes from react apex charts and it requires a couple of things first of all it's going to be options so this is like the uh configuration for your chart like what color do you want it how do you want it to kind of operate animations things like that series is going to be the data that it should receive uh the type that's going to be the type of chart and then also the size of the chart as well so only four props that we need and we'll go over all of these props in a bit and let's go to chart types and the chart type that we're going to use is called an area chart so this is going to be what we're using and if we just take a look right same thing so we know what we're going to set the type to um if we take a look at what else do we need okay so using the chart when we pass the series like i said the data should look like this right the x is going to be the time and the y is going to be the value or the price of the stock and we already configured that ourselves so we're already good to go on that that's why i format it ahead of time the other properties that we need is the x-axis should be set to type of date time so that's going to give us the time so let's just go ahead and just start playing with it and then just work on this one option at a time and so i'm going to import chart from be act apex charts i'm going to render out a div and let's define the options for our chart so we'll do const options so first of all let's give our title our chart our title and so if the configuration for the title first of all it's going to be the text what do we want the text or the title of the chart that's going to be the name of the stock so we have the symbol that we can just pass in we have to destructure that out from props so the text is going to be set to symbol align so how do we want to line up the text so it's going to be center and then we're going to make it just a little bit bigger so we'll set style and we'll do font size 24 pixels uh the next thing is going to be chart specific configuration so we're going to give this chart an id so we'll say stock data and then if you want you can also customize the animations and i'm just going to set this to be speed of 1300 next thing is going to be configuring the x-axis so we saw that in the documentation we have to set that to be date time because the x-axis is going to represent a time so type date time so let's try this out i think that's enough options let's set up the series so the series which is going to be the data that we passed to the chart is going to be an array and then an object for the configuration the reason it's array is because if you go back to the documentation you can have multiple series so multiple you know different types of data sets we just have one we just have one so that's why it asks for an array but we're only passing in one object and in this object we have to pass the name so this is going to be the symbol and then the data which is going to be day we're going to set it today for now just to take a look and now i'm going to add some style to this div to set the background color and we'll also give it some extra classes so add some margin to the top some padding shadow as well background is going to be white and i guess i didn't actually need this style we can actually delete that all right now we can pass in the chart component and so the options that's going to be set to that object that we created called options and the series is going to be set to series type is going to be set to area and width is going to be set to 100 percent okay and we can take a look at our chart and it actually looks pretty good so it's able to plot the data points however right now it's not using the correct uh time and that's because i wanted to show my local time so wherever i'm located i'm located on the east coast i wanted to show the east coast time uh and then when you know when you guys are using i wanted to show your local time and so to do that we can go up to x-axis right here set labels date time utc that defaults okay and that's better so that's better now if you take a look at the the tool tip right it says 25th of august i wanted to be a little bit more detailed i wanted to include the specific time stamp as well in the tool tip so we can go under x-axis here and add a tooltip configuration and the format i want this to be for the x-axis is going to be format and then we want mmm for the month the day and then i want the hour and then the minute so now we got the month day and the time as well the next thing that we need to implement is we have to provide the buttons for the users that they can select if they want to see uh the past 24 hours if they want to see seven days or one year's worth of data and we should be able to change between these and also obviously the color changes depending on if the stock gained or if the stock went down so going back to our app we're going to render out a couple of buttons right under the chart so i'm going to add another div and we're going to add a couple buttons and these buttons are gonna manage you know which one they've selected so we're gonna have to use uh we have we're gonna have to define some state we're gonna use the use state hook and i can call this uh what about i don't know date format i couldn't think of a better name and then set date format use date and then it's going to be 24 hours okay and so uh when the user wants to see one day's worth of data they're gonna set date format to 24 hours uh if they want to see um you know seven days we'll do seven days and if they want to see uh one year they'll say one year and so for these buttons we'll just set up a on click event handler and we'll say set date format to be uh the first button this is going to be for um one day so i'll say 24 hours and actually let me add the closing tag as well so now i can say 24 hours and i can copy this on click event handler and just paste it into the other two and just change this to be seven days and one year and then don't forget to import the eustate hook and so now we have these buttons and obviously we can add some style to them but now what we want to do is we want to update the data depending on which one is selected whether it's 24 hours one week or one year and i think the best way to do this is to define a function i'm going to define a function down here it's going to be very simple it's going to be called determine time format and we're just going to have a switch statement where we're going to switch on date format which is going to be the use date hook that we just created so whatever this is and if it's set to 24 hours we're going to return day so we're going to return the data from here and if it's seven days then we're going to return week and if it's one year we're going to return year and then we also have to provide a default and so if nothing is provided then we'll just return day as well and so now inside this series we can just change this to be determine time format we just run that it's going to return the correct data set so if i try seven days we could see it adjust one year and for the year we can see there's something goofy going on and that's because it added a lot of decimal values i think i remember seeing that also let me see if i can find that in the actual data set yeah so this data point right here so we're going to have to truncate it maybe we'll just grab you know two decimal points and so to fix this issue um what i'm actually going to do is if we go to the stock detail page where we fetch the data and then format the data when we format the value you can perform the truncation here so you know i said i was going to round to two i was going to keep two decimals but i think it's just easier just to remove the decimals so i'll do a math.floor and that's going to remove all the decimal points if you want to handle the logic for keeping two decimals you would just manipulate it right here yep and now we can see we just get whole numbers perfect all right so let's style these ugly buttons and on top of that let's also provide some feedback to the user which uh which one they've selected right if we take a look at the final app it highlights the one they've selected and to do this if we go to our stock chart we go to our button component for styling purposes what we want to do is add a couple of classes we want btn and btn-primary and that's going to give us this look and if we do btn outline dash primary right now we have the unselected look so that's the difference between selected and unselected is going to be this outline right here so how are we going to do this well i i think we should create another function to kind of handle this logic so i'm going to say render button select so this is going to handle all the styling as well as figuring out which button has been selected so all of the buttons are going to have the following classes they're going to have btn and then i'm also going to add a margin of 1 so they have a little space and then what i'm going to do is i'm going to say if button equals equals equals date format then we want to return classes plus btn-primary and i want to actually add a space here so what this is saying is if this button is um matched up with the selected button or the selected data set then we want to do btn primary which is going to give us the filled in color or else we will do the unfilled in one so we'll do return classes btn outline dash primary and so for each one of these buttons um i'm going to change the class name and we're going to just render that by calling render button select and then we're gonna pass in you know since this is the button for one day i'm gonna say 24 hours we'll copy this paste it to here this will be the seven days and this will be the one year and so what's really happening is um we're passing in one year so we're calling in uh we're calling in uh render button select into this button so button is gonna be set to one year and it says if one year equals equals date format which is whichever one is currently selected then we are going to make that the selected button however if they don't equal that then it's going to be the unselected button i think that should be everything that we need to do so we can see 24 is selected if i select one year one year selected seven days seven days perfect and the last thing that we got to do is we want the color to change based off of if the stock is going down or if it's going up so in this case it's going down it's red down red however it goes up that's green and this gets a little tricky but the colors can be specified in the options so here we would do colors and then you would provide an array and then here you would just provide your you know your hex color okay so uh we're going to first implement the logic for determining are we going down or are we going up this is where the math gets a little funky so i'll say const color this is going to be the color that we want equals so how do we figure out if the value is going up or down so to figure out how to do this i actually want to take a look at the data one more time so take a look at stock not stock chart chart data so we can better figure out what this is going to look like okay so this is what chart data looks like we can see that we get one for day week and year and the logic is going to be the same regardless of which data set we select so remember this is going to be the earliest uh this is going to be the uh first data point so if it's one year if we select one year this is going to be one year ago and then the last data point is going to be the current time so to figure out if the stock has gone up or down we take the current time the current y value and we subtract the first y value if that number is positive that means it went up if we if that number is negative then our stock went down simple as that and we have to do this for all of them so i'm going to define a variable called color now this also has to be aware of uh the the different um day week and year formats so we don't actually know which one selected so we have to run determine time format so that's going to return either day week or year depending on whichever one selected so this function will return that data set and the first thing that we want to do is we want to grab the last item in that array how do we do that well we can call that same function call the dot length and then subtract 1. so that's going to grab the last the last entry right so that's going to go all the way down and it's going to grab well this is the wrong one but that's because since we're typing this out there's going to be errors but that's going to grab the last entry and we want to subtract the first entry so we just run that determine time format we want to grab the first entry which is 0 and then we grab the y value and i forgot we should grab the y value on this one as well so hopefully that made sense all is doing is grabbing the last data point and subtracting the first data point and it's going to use this function to figure out which data set to work on so now we have color or now we have a boolean and we can use a ternary operator to say if it's positive if this value is greater than zero we're going to return this but if it's not greater than 0 then we're going to return this nasty red and then here we can change the colors and just pass in the color variable and i made a mistake i'm going to move this or actually i won't move this i'm going to move this determine time format function above this because it's referencing that so it needs to be above it now we can try that looks like things are working let's try seven days one year okay well they're all going down so let's uh let's go back and find i think what was the one we were looking at okay so that's going down it's red good red green perfect so now let's implement the uh delete or remove functionality so we should be able to hover over one of the rows and then remove it from the list and like i said i wanted to save this until we got the detail page working so that i can show you a little issue that we're going to run into and i was trying to figure out the best way to kind of implement a kind of a delete button or icon and i kind of got lazy so i just picked the simplest way so if we go to our stock list and you go down to the bottom where we render out the data all i'm doing is just adding a button in here i could have picked something a little bit classier but i was just the the idea is that we want to implement the logic that's what matters uh and so the logic is gonna be same regardless of what is the icon you use and where you put it so we're gonna put this button here this is going to say remove or delete whatever you want and let's give this a couple of classes so i'm going to say class name equals btn btn-danger btn-sm ml-3 and then d-inline-block and then we also want to add in a separate class called delete dash button so all of these come from the bootstrap library except for the delete button we'll implement this ourselves and so now we go back there's a remove button however we only want to show this when the user is hovering over the specific row so how do we do that well i'm going to go to our app.css i'm going to define some rules so i'm going to say we're going to reference that delete dash button and i'm going to say visibility by default is going to be set to hidden and then i don't think this is going to do anything but i see this in my notes so we'll just add it anyways then when we hover over a row we want the button to show so this gets a little tricky so we want to say when table dash row and if you recall what table row is we got to go back to stock list and table row where is it here we go table row right here so this class that goes uh assigned to the specific row when table row is hovered we want to select the delete dash button and then here all we do is just set visibility to visible simple as that and now if i hover there you go now we got the remove working so the next thing that we have to do is set up the uh the on click event handler so here's our button i'm gonna set the on click so here we're going to call the well we're going to have to grab the delete stock from our context so we'll call it delete stock and if you forgot where that's coming from that's just coming from our context api where we have this function that we're passing down that handles deleting it from the watch list so we'll say delete stock and then we want to pass in the symbol which is going to be accessible through stock data dot symbol and i think that should be it so let's take a look i'm gonna try to delete microsoft if i hit delete okay well something interesting happened it routes me to the next page so why is that happening well think about this when i click on this delete button technically i am clicking on this row on the row that this button is assigned to so if i go up to this row well where's the row i think i scroll too far the row this has a handle stock select uh on click event handler and if i go to handle stock select that's what handles the navigation so what's happening is when i click the button it's also triggering triggering this on click event handler and this is the issue that i wanted to show you guys so what's happening is that i do technically click on the remove button however the event bubbles up so it starts bubbling up all of these elements up to the to the tr and then it triggers this event handler or this on click event handler so that's the problem it's due to event bubbling so how do we avoid this well react gives us a handy thing we can call so we have to first get access to the event so i'm going to pass the event into the function and we just say e dot stop propagation so this is going to prevent the event from bubbling up to that parent component and this is apparently an a i've been mispronouncing it so now let's go back let's see can i remove microsoft perfect and you see microsoft got removed can i remove google perfect perfect and that's all we had to do for handling the deletion of an item from that list the next thing i want to do is implement the stock data component which is going to give out some extra information about the company uh like what was its ipo date what's the you know what's its market cap what's its website and things like that so let's go back to our components and let's create a new component and it's going to be called stock data we'll do export const stock data now the way that stock data works is that it's going to fetch data from a new api endpoint and i believe it's called company profile2 and so yeah this is the one that we want to use so we just send it to slashdoc profile2 and then you provide the symbol and it's going to give us all of that information that's all we got to do so let's handle fetching all the information and this component is actually going to accept a prop which is going to contain the symbol of the stock that we want to get information for so let's import the use date and use effect hook and then we'll call the use effect hook and let's go ahead and set the dependency array this is going to render anytime symbol changes anytime that prop changes and then we'll do const fetch data and let's import the api as well and i'm going to go a little bit faster for this um you guys have already seen this enough time so should already be second nature but here we can fetch the data and i'm going to do uh let's get the try catch block and so this is stock and then profile two and then the params is going to be the symbol only and if we go to our detail page we want to render this component out in the detail page and so i'm going to just render it right out right below the stock chart so let me import it sorry this should be stock data and i got some errors let's see and i actually already know the error so this should be apis okay and let's take a look at oh it doesn't look like it rendered out or no we need to i think i forgot to console log it no i logged that console logged it yep and i forgot the parentheses okay so we got that let's try this out now all right and so now we have all of the information about the company and so we can render that out now and that's really all this component is doing is just fetching a little data and then rendering it out but we do have to store this information in a use date hook so let me just do a const stock data set stock data that should be in the use effect hook and then right after here we'll say if is mounted then we want to set stock data to be response dot data and then we'll add the cleanup function and now it's just a matter of rendering rendering out um all of that data so this is now going to be changed to a div and i'm going to do that same expression where i say stock data if that's set and only if that's set will we then render out the rest of this and what we're going to render out let's see we'll start out with the div and we'll give this a couple classes so i'll say row border bg dash white rounded shadow dash sm p dash 4 and mt-5 and then within here we're going to have some divs this is going to have a class name of col and there's going to be three of these and then within each of these there's going to be three entries for the individual data points so i will say and let me not copy that i think that might confuse you guys so we'll say div and in this div we're going to have a span with the class name of fw bold and we're gonna have three of these within each one of those parent divs under call so i'm gonna add three in there and three in here and now we can just name the property so this one's going to be name this one's going to be the country this one will be the ticker this one will be the exchange we have the industry the ipo market cap shares outstanding and the url all right so now if we check this out and go back to the main page and okay so it's got all of the headers but it's not spread out the way it should be so i feel like i'm missing a class or two okay yeah i just had a uh a minor typo um that got messed up with the divs but now it's spread out across the three uh the three columns that i've defined and now it's just a matter of passing in that data into each section and we already have the different properties so if we want country we just do country currency exchange and so on so i'm just going to quickly go through this we have the stock data stored in this variable and we can just access it through that property so we'll say for the name we'll just do stock data dot name and i'm going to just copy these real quick across each one of them and then we'll update it individually we have the name the next one is going to be the country this one will be the ticker this one will be the exchange this one will be fin hub industry next one will be ipo and we have market capitalization share outstanding and then this last one is going to be a url to their website so i'm actually going to make this a a link and the href is going to be stock data dot web url and then for the the text you can make it whatever you want i mean you could just do the same thing if you wanted to just make it stock data.web url and let's give some spacing between these like i did for the other ones and i think that should be everything that we need here we go so that's going to wrap up the stock data component so the next feature that we need to add for this project is let's say that the user navigates to our website the first time we automatically populate these three stocks for them um and then let's say they go in and they search for a specific stock and let's say they want mcdonald's and then let's say they delete one of these other stocks if they navigate from this page or refresh the page guess what happens our website doesn't remember and it goes back to google microsoft amazon if you take a look at the final product the final product will remember uh any stock that we it remembers our entire watchlist so if i grab mcdonald's and i delete google i hit refresh it remembers it and the way that it does this is if we go to the chrome developer tools and we go into application and you go under storage local storage you can see that what i have done is i have stored the list of stocks that the user wants to keep track of in storage in local storage so that when we populate the website the next time they visit it we could just pull this list and then query that data so this is the next feature that we're going to implement and you're going to see that it's actually going to be pretty quick and pretty easy so this is all going to be done in the watchlist context because that's what handles the watch list and i'm going to import a use effect hook i'm going to add a use effect here and i want this hook to run whenever we change watch list so anytime watch list changes i want to go to local storage and then i want to set something so i'll do set item and the key is going to be called watch list and the data we're going to pass it is going to be our watch list now this use effect hook is going to run every time this provider component re-renders we don't really want to do that we want it to render every single time the watch list gets updated so we just say we set the dependency array to be watchlist and this really is the main use case for use effect so anytime something changes in your application and you want to update something kind of outside of your application like the local storage or a session um or some other property outside of your application you use a use effect hook and this is the perfect use case so this is going to set it and i think i forgot a t wait item so let's test this out so i'm going to add in tesla and now if i go to my application tab and we go to local storage we can see google microsoft amazon tesla so now if i refresh it remember well it didn't actually remember it but that's because we set it in our local storage however it's not actually pulling that information from the local storage so where do we actually where and when do we pull this from the local storage well it's going to be in this u-state hook so when this u-state hook runs the first thing it should do is and i'm going to copy this for a second and i'm just going to paste it here make this a comment and i'm going to put this across multiple lines so when the the default state for our hook should be when our application first loads we should look into local storage and we should call get item for watchlist so this is going to give us a string and if we actually take a look at it it just gives us this string so we have to turn it into an array so how do we turn it into array we call a dot split method and we want to split it every time we see a comma and if we don't have anything in local storage then we're just going to default to this does that make sense right remember this is just a string when you read and write to local storage it's just a plain string right and so when we call the split method it's going to split it wherever there's a comma and it's going to add that as an entry into a list so let's try this out now i'm going to add tesla okay tesla's in there let's refresh and it remembers tesla let's remove microsoft does it remember that it does in fact remember that and keep in mind i have to refresh this so if i yeah we could see microsoft's not there now i'm going to show you a bug in our application if i go to my watch list and delete it and i hit refresh nothing shows up what's going on well let's see if there's something in the console and we can see the air says cannot read properties of null so what happened well our application loads the provider loads and then it runs this uh you state hook where it sets the default value so it does so it looks into local storage it tries to get item watch list keep in mind if we go to our application in here we can see there is no watch list so this returns nothing and if you try to uh this returns undefined and if you try to perform a dot split on an undefined that's the exact error that we're getting right cannot read properties of null reading split we can't we can't call split on null so how do we get around this issue very simple you just put a question mark right here so what this question mark does is it's going to check to see if this actually exists if it doesn't it's just going to return a null and it's not going to run this code i think this is called null coalescing i can never remember the terms but yeah so all this does is check to see if it exists if it exists perfect we'll just run the next code if it doesn't exist it's going to return null and if this returns null then we just default to this so let's try this again okay and look at that it defaulted to the three despite the fact that we had cleared the local storage and we can just test this out once again and that's perfect so it looks like it's working i'm going to remove this stack overview page we don't need that let's see where is that stock overview okay guys so that's going to wrap up this project we've implemented all of the features uh that i wanted we've gotten a chance to learn a lot of different features and functionalities within the react ecosystem things like the context api react router we've gotten a chance to work with different libraries and apis like the apex charge library as well as the finhub api and uh hopefully you guys enjoyed this project and i will see you guys in the next one we've reached the end of the course not only have you learned the basics of react you also coded three react projects good luck to using this knowledge to create your own react applications\n"