1 00:00:00,000 --> 00:00:02,994 [PIANO PLAYING] 2 00:00:02,994 --> 00:00:11,477 3 00:00:11,477 --> 00:00:14,190 SPEAKER: OK, let's get started. 4 00:00:14,190 --> 00:00:16,490 Welcome back, everyone, to CS50 Beyond. 5 00:00:16,490 --> 00:00:17,610 Our goal for today-- 6 00:00:17,610 --> 00:00:19,730 this is the second-to-last day of the course. 7 00:00:19,730 --> 00:00:21,530 And goal for today is going to be to pick up really 8 00:00:21,530 --> 00:00:22,700 where we left off yesterday. 9 00:00:22,700 --> 00:00:26,000 So yesterday we introduced a new JavaScript library called React. 10 00:00:26,000 --> 00:00:28,490 And React was designed to make it easier for us to build 11 00:00:28,490 --> 00:00:30,500 interactive and dynamic web pages. 12 00:00:30,500 --> 00:00:35,540 And we did so by creating components and ultimately via declarative programming, 13 00:00:35,540 --> 00:00:38,660 where we were describing what it is that the page should look like, 14 00:00:38,660 --> 00:00:42,090 whether certain variables should belong in certain places on the page, 15 00:00:42,090 --> 00:00:44,840 whether we should be iterating over a particular variable in order 16 00:00:44,840 --> 00:00:46,760 to display a list of things on the page. 17 00:00:46,760 --> 00:00:49,672 And then the only thing we needed to do in order to edit the page was 18 00:00:49,672 --> 00:00:52,130 rather than go into the dom and manipulate the dom and say, 19 00:00:52,130 --> 00:00:54,950 update this element or update that element, we would just say, 20 00:00:54,950 --> 00:00:55,970 change the data. 21 00:00:55,970 --> 00:00:58,610 Set the state of the component to be something different. 22 00:00:58,610 --> 00:01:01,010 And the page would automatically render and re-update 23 00:01:01,010 --> 00:01:05,400 the parts of the page that needed to in order to reflect those changes. 24 00:01:05,400 --> 00:01:08,570 And so the goal of today is to continue along those lines and in particular, 25 00:01:08,570 --> 00:01:11,338 emphasize thinking in React, thinking about how 26 00:01:11,338 --> 00:01:13,630 it is that we take an application that we're going for, 27 00:01:13,630 --> 00:01:17,012 decompose it into pieces, and then try and put it back together, such 28 00:01:17,012 --> 00:01:19,220 that we can figure out what components, what state we 29 00:01:19,220 --> 00:01:21,590 need to keep track of in order to make our applications 30 00:01:21,590 --> 00:01:22,910 interactive and useful. 31 00:01:22,910 --> 00:01:26,330 Along the way we'll talk about things like React lifecycle 32 00:01:26,330 --> 00:01:29,168 and about how to get your React applications, which 33 00:01:29,168 --> 00:01:32,210 are front-end applications, to interact with the back end, like a server, 34 00:01:32,210 --> 00:01:34,130 for instance, connecting to APIs then. 35 00:01:34,130 --> 00:01:38,100 And then we'll have some opportunity for hands-on projects, as before. 36 00:01:38,100 --> 00:01:41,632 And so we'll start by taking a look at an example from yesterday 37 00:01:41,632 --> 00:01:43,340 and begin to answer some of the questions 38 00:01:43,340 --> 00:01:45,905 that yesterday I pushed off until today. 39 00:01:45,905 --> 00:01:50,510 And so we'll take a look at counter.html And counter.html, 40 00:01:50,510 --> 00:01:53,240 you'll recall from yesterday, was just an application 41 00:01:53,240 --> 00:01:56,180 whereby it displayed a number that defaulted to the number 0. 42 00:01:56,180 --> 00:01:59,330 And then we had increment and decrement buttons, or plus and minus buttons, 43 00:01:59,330 --> 00:02:02,090 where all those buttons' data will change the value of the number. 44 00:02:02,090 --> 00:02:03,200 We started with 0. 45 00:02:03,200 --> 00:02:07,220 We can go 1, 2, 3, 4, 5 by clicking the Increment button plus the Minus button 46 00:02:07,220 --> 00:02:09,310 in order to go back down. 47 00:02:09,310 --> 00:02:11,060 And ultimately the way that we implemented 48 00:02:11,060 --> 00:02:19,970 that program was to say inside of counter.html, 49 00:02:19,970 --> 00:02:23,150 we had some state inside of our counter component 50 00:02:23,150 --> 00:02:26,030 that initially was just set to the number 0. 51 00:02:26,030 --> 00:02:29,510 And then when we click the On-click button for the plus or minus buttons, 52 00:02:29,510 --> 00:02:32,120 we would call the increment or decrement functions. 53 00:02:32,120 --> 00:02:34,620 And all those increment and decrement functions would do 54 00:02:34,620 --> 00:02:38,720 is call the this.setState method, which is a special method in React that 55 00:02:38,720 --> 00:02:41,810 takes the state and updates it, in particular by taking the count 56 00:02:41,810 --> 00:02:44,870 and setting it to whatever the count minus 1 is in the case of decrement, 57 00:02:44,870 --> 00:02:48,410 and in the case of increment, taking the count and adding 1 to it. 58 00:02:48,410 --> 00:02:51,230 Of course, this state only exists when this component 59 00:02:51,230 --> 00:02:52,920 is loaded onto the screen. 60 00:02:52,920 --> 00:02:54,988 And as soon as we close the page and reopen it, 61 00:02:54,988 --> 00:02:56,780 we're getting a brand-fresh, new component. 62 00:02:56,780 --> 00:02:58,620 It's remount onto the screen. 63 00:02:58,620 --> 00:03:03,290 And as a result, if I increase the number to, say, 5, for example, 64 00:03:03,290 --> 00:03:08,750 close the page, and then reopen the counter.html, we're back to 0, right? 65 00:03:08,750 --> 00:03:09,710 We reloaded the page. 66 00:03:09,710 --> 00:03:11,180 The JavaScript is rerun. 67 00:03:11,180 --> 00:03:15,410 And as a result, our state is reset back to the initial state 68 00:03:15,410 --> 00:03:20,055 as defined by the constructor, which, in this case, is the number 0. 69 00:03:20,055 --> 00:03:22,430 Now, before we got to the world of React and we were just 70 00:03:22,430 --> 00:03:26,052 dealing with plain JavaScript, how do we solve this problem, 71 00:03:26,052 --> 00:03:28,760 if we wanted the state to persist between when you open the page, 72 00:03:28,760 --> 00:03:30,052 closed the page, open it again? 73 00:03:30,052 --> 00:03:32,530 74 00:03:32,530 --> 00:03:34,585 We cached it in a place called local storage, 75 00:03:34,585 --> 00:03:36,850 a place within the browser, whereby we could 76 00:03:36,850 --> 00:03:40,240 say I want to store the state of the application inside of local storage, 77 00:03:40,240 --> 00:03:44,200 such that later on in my application I can refer back to local storage 78 00:03:44,200 --> 00:03:49,030 and say, get this value out of local storage and put it into my application. 79 00:03:49,030 --> 00:03:51,640 And in React, we can do something very similar. 80 00:03:51,640 --> 00:03:55,360 Every React component has a number of what are called lifecycle methods, 81 00:03:55,360 --> 00:03:59,830 or functions that are going to run at a particular point in the component's 82 00:03:59,830 --> 00:04:00,800 life. 83 00:04:00,800 --> 00:04:03,010 And one of the most common is a special function 84 00:04:03,010 --> 00:04:06,512 in React called componentDidMount. 85 00:04:06,512 --> 00:04:07,720 There are a number of others. 86 00:04:07,720 --> 00:04:10,428 The only one we're going to talk about today is componentDidMount 87 00:04:10,428 --> 00:04:12,910 And componentDidMount is a special method in React 88 00:04:12,910 --> 00:04:16,810 that is going to run as soon as a component is mounted into the dom. 89 00:04:16,810 --> 00:04:20,360 In other words, as soon as we add this component into the dom, 90 00:04:20,360 --> 00:04:24,233 this is the method that's going to run before it actually ultimately renders 91 00:04:24,233 --> 00:04:25,900 the contents of what's going to show up. 92 00:04:25,900 --> 00:04:29,560 So any work we want to do of, like, setting up the component, 93 00:04:29,560 --> 00:04:33,500 we can do inside of componentDidMount. 94 00:04:33,500 --> 00:04:37,870 And so one thing we can do, for example, is get something out of local storage. 95 00:04:37,870 --> 00:04:44,940 I can say, local storage.getItem count in order 96 00:04:44,940 --> 00:04:50,600 to say, all right, let me get the count value out of local storage. 97 00:04:50,600 --> 00:04:55,770 And I'll save that inside of a variable that I'm just going to call count. 98 00:04:55,770 --> 00:04:58,130 So if there was an item called count in local storage, 99 00:04:58,130 --> 00:05:00,140 I'm going to extract it from local storage 100 00:05:00,140 --> 00:05:03,410 and save it inside of a variable called count. 101 00:05:03,410 --> 00:05:07,610 Now, there's a chance that there was no count item in local storage, 102 00:05:07,610 --> 00:05:10,080 that this is not equal to any particular value. 103 00:05:10,080 --> 00:05:13,430 And so it's possible that count is going to be equal to null. 104 00:05:13,430 --> 00:05:14,810 So let me just do a check. 105 00:05:14,810 --> 00:05:18,770 Let me check if count is not equal to null, 106 00:05:18,770 --> 00:05:23,157 meaning there actually was some count saved inside of local storage, 107 00:05:23,157 --> 00:05:24,990 well, then what I'm going to do is I'm going 108 00:05:24,990 --> 00:05:36,720 to call this.setState, setting the count equal to the result of parse int count. 109 00:05:36,720 --> 00:05:41,640 It's going to be stored as a string so we'll parse it as an integer 110 00:05:41,640 --> 00:05:45,800 in order to update the state of the application. 111 00:05:45,800 --> 00:05:49,010 So componentDidMount, if you think about the chronology of things, 112 00:05:49,010 --> 00:05:51,500 is going to happen after we've constructed this component 113 00:05:51,500 --> 00:05:53,450 and inserted it into the dom. 114 00:05:53,450 --> 00:05:55,460 And we want some initial code to be running 115 00:05:55,460 --> 00:05:57,710 at the beginning of this component's life, 116 00:05:57,710 --> 00:06:01,640 whereby we're saying from local storage, let's extract the counter variable. 117 00:06:01,640 --> 00:06:04,580 And as long as it's not null, then go ahead and update the state, 118 00:06:04,580 --> 00:06:08,150 setting count equal to the result of parsing 119 00:06:08,150 --> 00:06:13,600 the int of whatever the value of the count variable is. 120 00:06:13,600 --> 00:06:16,530 So now we have a component that can read from local storage 121 00:06:16,530 --> 00:06:19,461 and update its initial state based on that information. 122 00:06:19,461 --> 00:06:22,230 123 00:06:22,230 --> 00:06:24,720 What's the missing half of this now? 124 00:06:24,720 --> 00:06:25,406 Yeah? 125 00:06:25,406 --> 00:06:29,310 AUDIENCE: [INAUDIBLE] isn't count equal to count? 126 00:06:29,310 --> 00:06:32,520 Why [INAUDIBLE]? 127 00:06:32,520 --> 00:06:34,380 SPEAKER: So the way local storage is going 128 00:06:34,380 --> 00:06:37,165 to store things is it's going to store the values of strings. 129 00:06:37,165 --> 00:06:40,290 And so that's the way that most browsers choose to implement local storage. 130 00:06:40,290 --> 00:06:42,250 And so when we read them from local storage, 131 00:06:42,250 --> 00:06:44,610 we have to assume that what's coming into us will be strings. 132 00:06:44,610 --> 00:06:47,568 And so we can parse them into integers in order to be able to use them. 133 00:06:47,568 --> 00:06:53,105 134 00:06:53,105 --> 00:06:55,980 So we've got saving things-- or retrieving things from local storage. 135 00:06:55,980 --> 00:06:57,510 And now that I just gave away the missing piece of this 136 00:06:57,510 --> 00:07:01,090 is saving things into local storage, whereby we're getting the item count, 137 00:07:01,090 --> 00:07:02,880 but we're never setting the item count. 138 00:07:02,880 --> 00:07:06,450 And so we want this to happen before the window goes away. 139 00:07:06,450 --> 00:07:09,960 If ever I try to close the window, we want something to happen there. 140 00:07:09,960 --> 00:07:12,125 And so we'd like to add some sort of event listener 141 00:07:12,125 --> 00:07:15,365 for when I try to close the window, for example. 142 00:07:15,365 --> 00:07:17,490 And oftentimes you might see other web applications 143 00:07:17,490 --> 00:07:19,500 that have implemented something similar, whereby 144 00:07:19,500 --> 00:07:22,100 if you try to exit out of a web document before saving, 145 00:07:22,100 --> 00:07:23,850 you might get a warning message that says, 146 00:07:23,850 --> 00:07:26,130 are you sure you want to leave this page without saving your changes, 147 00:07:26,130 --> 00:07:26,730 for example. 148 00:07:26,730 --> 00:07:28,320 Or you haven't completed this action. 149 00:07:28,320 --> 00:07:29,945 Are you sure you want to do this thing? 150 00:07:29,945 --> 00:07:34,140 And so just in the same way that we were able to add event listeners to when 151 00:07:34,140 --> 00:07:36,660 the dom is done loading or when you click on a button, 152 00:07:36,660 --> 00:07:38,730 we can also add an event listener to the window 153 00:07:38,730 --> 00:07:41,610 to say, like, before this window's contents are unloaded, 154 00:07:41,610 --> 00:07:43,560 let's run some particular code. 155 00:07:43,560 --> 00:07:49,050 And so to do that, I'll say window.addEventListener. 156 00:07:49,050 --> 00:07:51,630 And the name of this event that we're going to be using 157 00:07:51,630 --> 00:07:56,040 is a special event called before unload. 158 00:07:56,040 --> 00:07:59,700 In other words, before this window's contents are unloaded, 159 00:07:59,700 --> 00:08:00,990 let's run some code. 160 00:08:00,990 --> 00:08:04,980 Before we get rid of this component, let's run a function. 161 00:08:04,980 --> 00:08:10,800 And that function is going to say local storage.setItem. 162 00:08:10,800 --> 00:08:13,030 And then setItem, again, takes two arguments. 163 00:08:13,030 --> 00:08:15,960 The first is the key, the name of the thing that we're setting. 164 00:08:15,960 --> 00:08:19,080 And the second is the value, what value it should take on. 165 00:08:19,080 --> 00:08:22,620 The key, as with line 22, we got the item with key count. 166 00:08:22,620 --> 00:08:26,530 So we should be setting the item with key count. 167 00:08:26,530 --> 00:08:27,650 And what is the value? 168 00:08:27,650 --> 00:08:31,502 169 00:08:31,502 --> 00:08:33,210 What should we be setting count equal to? 170 00:08:33,210 --> 00:08:37,057 171 00:08:37,057 --> 00:08:37,557 Yeah? 172 00:08:37,557 --> 00:08:38,682 AUDIENCE: This.state.count? 173 00:08:38,682 --> 00:08:40,809 SPEAKER: This.state.count, perfect. 174 00:08:40,809 --> 00:08:43,570 We want to set count equal to whatever the current value of count 175 00:08:43,570 --> 00:08:45,720 is inside of this component state. 176 00:08:45,720 --> 00:08:47,470 To get to this component state, we can say 177 00:08:47,470 --> 00:08:49,652 this.state to get at the state of the component 178 00:08:49,652 --> 00:08:52,360 and then dot count it to say, all right, let's go into the state, 179 00:08:52,360 --> 00:08:55,840 extract the thing with the key count, and use that as the value 180 00:08:55,840 --> 00:08:57,920 that we save into local storage. 181 00:08:57,920 --> 00:08:59,920 And so assuming I didn't make any mistakes here, 182 00:08:59,920 --> 00:09:03,090 if I go back to the page, refresh the page, 183 00:09:03,090 --> 00:09:06,280 I can increment the counter 1, 2, 3, 4, 5. 184 00:09:06,280 --> 00:09:08,610 And now if I close the counter, that's going 185 00:09:08,610 --> 00:09:12,900 to trigger the window.beforeUnload event, which 186 00:09:12,900 --> 00:09:15,620 is going to save the number 5 into local storage. 187 00:09:15,620 --> 00:09:20,083 And if I open counter.html again, press Return, all right, great, 188 00:09:20,083 --> 00:09:21,750 the component now shows me the number 5. 189 00:09:21,750 --> 00:09:24,930 It's been able to save that state inside of local storage, 190 00:09:24,930 --> 00:09:27,840 such that even when I closed the page and open it back up again, 191 00:09:27,840 --> 00:09:31,460 I've been able to maintain the state of the application. 192 00:09:31,460 --> 00:09:31,960 Yeah? 193 00:09:31,960 --> 00:09:35,320 AUDIENCE: [INAUDIBLE] 194 00:09:35,320 --> 00:09:36,672 195 00:09:36,672 --> 00:09:38,380 SPEAKER: For refreshing the page as well? 196 00:09:38,380 --> 00:09:41,740 Yeah, if you refresh the page, if I go to 10, for example, and click Refresh, 197 00:09:41,740 --> 00:09:44,950 it stays at 10 because before the contents of the page 198 00:09:44,950 --> 00:09:49,650 are unloaded before the refresh, it's going to trigger that event listener. 199 00:09:49,650 --> 00:09:50,150 Yeah? 200 00:09:50,150 --> 00:09:52,810 AUDIENCE: Are the items that are kept in local storage-- 201 00:09:52,810 --> 00:09:59,030 like say you want [INAUDIBLE] the program [INAUDIBLE].. 202 00:09:59,030 --> 00:10:03,540 Are the items in local storage, are they secure from-- 203 00:10:03,540 --> 00:10:07,610 if someone hacked into your code, broke in, could they get into it? 204 00:10:07,610 --> 00:10:10,130 SPEAKER: The items inside of local storage 205 00:10:10,130 --> 00:10:12,590 are actually quite accessible to anyone. 206 00:10:12,590 --> 00:10:16,250 So anyone who could get access to the browser could get access to it, 207 00:10:16,250 --> 00:10:22,490 insofar as all I need to do is go into inspect, and I can go into, I think, 208 00:10:22,490 --> 00:10:25,788 it's application, at least in Chrome, and go to local storage. 209 00:10:25,788 --> 00:10:28,580 And over here I see a count and also a counter from a previous time 210 00:10:28,580 --> 00:10:30,705 that I was doing an application with local storage. 211 00:10:30,705 --> 00:10:32,750 So these values are highly accessible. 212 00:10:32,750 --> 00:10:34,260 And you can edit them as well. 213 00:10:34,260 --> 00:10:36,865 And so probably best not to store anything super secure inside 214 00:10:36,865 --> 00:10:38,240 of local storage for that reason. 215 00:10:38,240 --> 00:10:40,680 You'll probably want to store things on the server side. 216 00:10:40,680 --> 00:10:44,530 And we'll talk about interaction with server side in just a moment. 217 00:10:44,530 --> 00:10:45,030 Yeah? 218 00:10:45,030 --> 00:10:47,280 AUDIENCE: Will you let me know the website [INAUDIBLE] 219 00:10:47,280 --> 00:10:49,550 variables that you put in local storage [INAUDIBLE]?? 220 00:10:49,550 --> 00:10:52,020 SPEAKER: Local storage is domain specific. 221 00:10:52,020 --> 00:10:56,240 So if you have domain1.com, and you're storing things inside of local storage, 222 00:10:56,240 --> 00:10:59,270 domain2.com is going to have access to a different local storage. 223 00:10:59,270 --> 00:11:01,541 And so those are kept separate. 224 00:11:01,541 --> 00:11:07,360 AUDIENCE: Is there a way to make it so local pages use the same [INAUDIBLE]?? 225 00:11:07,360 --> 00:11:09,850 SPEAKER: So, yeah, if they're within the same domain, 226 00:11:09,850 --> 00:11:11,630 they can use the same local storage. 227 00:11:11,630 --> 00:11:14,467 For example, if I were to create another file-- 228 00:11:14,467 --> 00:11:15,550 and I'll just demonstrate. 229 00:11:15,550 --> 00:11:20,950 Like, if I just copy counter.html and call it, like, newcounter.html, 230 00:11:20,950 --> 00:11:24,432 which is a different file, and I open up newcounter.html, 231 00:11:24,432 --> 00:11:26,890 it's still going to have access to that same local storage. 232 00:11:26,890 --> 00:11:29,030 It still has access to the number 10. 233 00:11:29,030 --> 00:11:30,655 So it can draw up on those same values. 234 00:11:30,655 --> 00:11:36,010 235 00:11:36,010 --> 00:11:37,220 Other things? 236 00:11:37,220 --> 00:11:37,720 Yeah? 237 00:11:37,720 --> 00:11:40,470 AUDIENCE: Can you just explain a little bit more of the difference 238 00:11:40,470 --> 00:11:45,627 between componentDidMount and why do we need didMount [INAUDIBLE]?? 239 00:11:45,627 --> 00:11:46,210 SPEAKER: Yeah. 240 00:11:46,210 --> 00:11:49,775 So componentDidMount, there are a number of what 241 00:11:49,775 --> 00:11:52,900 are called lifecycle methods in React, which are canonical places where you 242 00:11:52,900 --> 00:11:55,330 can put code, and you can guarantee that React 243 00:11:55,330 --> 00:11:57,890 will call upon those functions at particular times. 244 00:11:57,890 --> 00:12:01,660 And so in fact, so componentDidMount is one of them. 245 00:12:01,660 --> 00:12:03,910 ComponentWillUnmount is another one of them 246 00:12:03,910 --> 00:12:06,730 that React offers, which is sort of the inverse of that, 247 00:12:06,730 --> 00:12:10,470 which is when we're about to remove information from the dom. 248 00:12:10,470 --> 00:12:13,180 There's even a componentWillUpdate for whenever 249 00:12:13,180 --> 00:12:15,850 a component is going to refresh itself and change something 250 00:12:15,850 --> 00:12:16,930 about its behavior. 251 00:12:16,930 --> 00:12:20,000 And so there are a lot of these different lifecycle methods 252 00:12:20,000 --> 00:12:22,000 and more than we'll probably have time to really 253 00:12:22,000 --> 00:12:24,067 be able to talk about over the course of today. 254 00:12:24,067 --> 00:12:25,650 But I'd encourage you to look at them. 255 00:12:25,650 --> 00:12:27,940 There are great flow charts online of what it looks like 256 00:12:27,940 --> 00:12:29,523 and when different methods are called. 257 00:12:29,523 --> 00:12:32,140 And each one is called at a slightly different time. 258 00:12:32,140 --> 00:12:34,840 And so getting an understanding for when each of them are called 259 00:12:34,840 --> 00:12:37,030 can help you to really fine tune a component 260 00:12:37,030 --> 00:12:39,430 to make sure that it behaves in particular ways 261 00:12:39,430 --> 00:12:41,710 and only running certain code when it needs to run. 262 00:12:41,710 --> 00:12:46,170 263 00:12:46,170 --> 00:12:47,170 So that's local storage. 264 00:12:47,170 --> 00:12:49,990 So a couple of people were asking about how do you save React component states, 265 00:12:49,990 --> 00:12:52,490 such that it's available the next time you load the program. 266 00:12:52,490 --> 00:12:54,170 And that's certainly one way to do it. 267 00:12:54,170 --> 00:12:57,400 And so far with regards to React, all of our programs 268 00:12:57,400 --> 00:13:01,170 have been just front-end applications, right? 269 00:13:01,170 --> 00:13:02,850 They just exist in the browser. 270 00:13:02,850 --> 00:13:04,973 There's no interaction with a back-end server, 271 00:13:04,973 --> 00:13:08,140 with a database, like we were doing when we were working with Flask and SQL, 272 00:13:08,140 --> 00:13:09,490 for example. 273 00:13:09,490 --> 00:13:11,830 And so there are certainly ways that we can do that. 274 00:13:11,830 --> 00:13:13,210 And the example that we'll use is we'll take 275 00:13:13,210 --> 00:13:15,210 an example that we did back when we were working 276 00:13:15,210 --> 00:13:18,380 and just plain JavaScript, which is that of currency conversion. 277 00:13:18,380 --> 00:13:23,330 So you probably recall that we had api.exchangeratesapi.io. 278 00:13:23,330 --> 00:13:27,580 And if I go to a particular URL, like slash latest, 279 00:13:27,580 --> 00:13:30,310 and then specify the base being US dollars, 280 00:13:30,310 --> 00:13:34,750 then I get all sorts of these different exchange rates in terms of US dollars, 281 00:13:34,750 --> 00:13:41,020 that one US dollar is equal to 1.3312 Canadian dollars, for example, and so 282 00:13:41,020 --> 00:13:42,690 on and so forth. 283 00:13:42,690 --> 00:13:45,610 And so what I'd like to do is create a React application 284 00:13:45,610 --> 00:13:48,310 that is going to be able to use these currency exchange rates. 285 00:13:48,310 --> 00:13:51,580 And it's going to be a fair bit more interactive than the previous one 286 00:13:51,580 --> 00:13:55,070 that we created was, in particular, because React 287 00:13:55,070 --> 00:13:58,250 is going to make it easier for us to dynamically update the page. 288 00:13:58,250 --> 00:14:05,000 So if I go in to exchange0.html, an application we might create 289 00:14:05,000 --> 00:14:07,050 is going to look a little something like this, 290 00:14:07,050 --> 00:14:10,400 whereby I have two drop-downs, each of which I can select a currency. 291 00:14:10,400 --> 00:14:11,790 This one's saying US dollars. 292 00:14:11,790 --> 00:14:13,880 This one's saying euros, at least for now. 293 00:14:13,880 --> 00:14:18,090 And I can say, all right, one US dollar is equal to that many euros. 294 00:14:18,090 --> 00:14:21,295 I can say, all right, 15 US dollars is equal to that many euros. 295 00:14:21,295 --> 00:14:24,420 And it's going to dynamically calculate for me what the exchange rates are. 296 00:14:24,420 --> 00:14:27,668 If I change euros to pounds, for example, 297 00:14:27,668 --> 00:14:30,210 it tells me the exchange rates between US dollars and pounds. 298 00:14:30,210 --> 00:14:33,410 And so we can get these exchange rates, much as any currency converter 299 00:14:33,410 --> 00:14:36,660 app that you may have used before might work, by just selecting the currencies 300 00:14:36,660 --> 00:14:40,890 we want, typing in into the input field what it is is the amount 301 00:14:40,890 --> 00:14:43,770 that we want to convert, and then see in this other field what 302 00:14:43,770 --> 00:14:46,750 that converted amount is equal to. 303 00:14:46,750 --> 00:14:50,640 And so this is the application that we're going to be building. 304 00:14:50,640 --> 00:14:54,480 I'll go ahead and create a new file. 305 00:14:54,480 --> 00:14:57,980 We'll call it exchange.html. 306 00:14:57,980 --> 00:15:01,700 And for now I'm going to copy the contents of counter, paste it in here, 307 00:15:01,700 --> 00:15:07,192 and we'll get rid of the counter component because I don't need it. 308 00:15:07,192 --> 00:15:09,510 I'll change the title to Exchange. 309 00:15:09,510 --> 00:15:12,060 310 00:15:12,060 --> 00:15:16,066 And what do we need inside of our application? 311 00:15:16,066 --> 00:15:24,330 312 00:15:24,330 --> 00:15:26,130 Any thoughts as to what type of information 313 00:15:26,130 --> 00:15:28,080 needs to be in the state of this application? 314 00:15:28,080 --> 00:15:31,680 What things can change in the application that we had before? 315 00:15:31,680 --> 00:15:37,632 316 00:15:37,632 --> 00:15:38,630 AUDIENCE: [INAUDIBLE] 317 00:15:38,630 --> 00:15:40,680 SPEAKER: Yeah, the base currency that I select. 318 00:15:40,680 --> 00:15:43,597 So we need some sort of base currency that we're storing in the state. 319 00:15:43,597 --> 00:15:45,980 By default, my original application just used US dollars 320 00:15:45,980 --> 00:15:48,270 as the initial value of the base currency. 321 00:15:48,270 --> 00:15:51,200 And we also needed some way of storing the other currency, whatever 322 00:15:51,200 --> 00:15:53,070 else that I typed in. 323 00:15:53,070 --> 00:15:54,530 So go ahead and type in other. 324 00:15:54,530 --> 00:15:57,197 And then I think by default my application said let's make euros 325 00:15:57,197 --> 00:16:00,772 the other currency by default. But you can switch them up. 326 00:16:00,772 --> 00:16:01,730 What else could change? 327 00:16:01,730 --> 00:16:04,600 328 00:16:04,600 --> 00:16:05,100 Yeah? 329 00:16:05,100 --> 00:16:06,923 AUDIENCE: The amount of base currency? 330 00:16:06,923 --> 00:16:09,840 SPEAKER: The amount of the base currency, yeah, so some sort of volume 331 00:16:09,840 --> 00:16:11,160 that initially was 0. 332 00:16:11,160 --> 00:16:14,740 And then there was also the converted value that was also 0 to begin with. 333 00:16:14,740 --> 00:16:18,240 And so I'll go ahead and create another key inside the state called converted 334 00:16:18,240 --> 00:16:22,000 and set that equal to 0 as well. 335 00:16:22,000 --> 00:16:23,970 So we have this.state. 336 00:16:23,970 --> 00:16:27,590 And in addition to having these currencies, the base currency 337 00:16:27,590 --> 00:16:29,400 and the other currency, the dropdown list 338 00:16:29,400 --> 00:16:31,812 also had a list of all the possible currency. 339 00:16:31,812 --> 00:16:34,770 That's a list that I might want to have programmatically inside my code 340 00:16:34,770 --> 00:16:37,380 so that it's easy to update if I ever want to add more. 341 00:16:37,380 --> 00:16:42,390 So for sake of example, I'm just going to add this.currencies, 342 00:16:42,390 --> 00:16:44,820 a new variable, just called currencies, stored 343 00:16:44,820 --> 00:16:46,710 inside of this component that's just going 344 00:16:46,710 --> 00:16:49,620 to be equal to a list of possible currencies 345 00:16:49,620 --> 00:16:52,320 that I want to allow people to exchange between, 346 00:16:52,320 --> 00:16:56,190 so maybe Australian dollars and Canadian dollars, 347 00:16:56,190 --> 00:16:59,220 each one just using their three letter ISO code 348 00:16:59,220 --> 00:17:02,000 for what the abbreviation for that currency happens to be. 349 00:17:02,000 --> 00:17:02,980 We'll do francs. 350 00:17:02,980 --> 00:17:04,349 We'll allow those. 351 00:17:04,349 --> 00:17:05,700 Chinese yuan we'll allow. 352 00:17:05,700 --> 00:17:07,500 Indian rupees we'll allow. 353 00:17:07,500 --> 00:17:09,460 We should do US dollars and euros. 354 00:17:09,460 --> 00:17:11,790 We'll do pounds, yen. 355 00:17:11,790 --> 00:17:14,847 And we'll also do New Zealand dollars. 356 00:17:14,847 --> 00:17:16,680 So there are more currencies than just this. 357 00:17:16,680 --> 00:17:21,880 But we'll just do a small sampling of currencies for the sake of example. 358 00:17:21,880 --> 00:17:27,612 Semicolon there, and, OK, we've defined the initial state of this component. 359 00:17:27,612 --> 00:17:29,070 And now let's render the component. 360 00:17:29,070 --> 00:17:32,020 What should it actually look like when we try and render it? 361 00:17:32,020 --> 00:17:34,020 Well, if you remember what the page looked like, 362 00:17:34,020 --> 00:17:36,780 there was a select menu and an input field 363 00:17:36,780 --> 00:17:39,300 up top for the base currency and then a select menu 364 00:17:39,300 --> 00:17:42,450 and an input field underneath it for the other currency. 365 00:17:42,450 --> 00:17:47,160 So I'll go ahead and create two divs inside of my outer div. 366 00:17:47,160 --> 00:17:49,810 The first of which is going to be for the base currency. 367 00:17:49,810 --> 00:17:52,830 And the second of which is going to be for the other currency. 368 00:17:52,830 --> 00:17:56,550 So the base currency is going to have a select menu. 369 00:17:56,550 --> 00:18:00,240 And the select menu is going to have a name of base. 370 00:18:00,240 --> 00:18:02,780 371 00:18:02,780 --> 00:18:07,160 And for now I'll just say select name as base and slash select to end it 372 00:18:07,160 --> 00:18:09,060 that we'll add to this in just a moment. 373 00:18:09,060 --> 00:18:14,650 And in the other div, I'll have a select menu, whose name is Other. 374 00:18:14,650 --> 00:18:16,300 And that'll also be a select menu. 375 00:18:16,300 --> 00:18:21,190 So I now have a base select menu on top of another select menu. 376 00:18:21,190 --> 00:18:23,890 And the value of this select menu, like which 377 00:18:23,890 --> 00:18:29,170 item is chosen in the select menu, is going to be represented by which part 378 00:18:29,170 --> 00:18:32,095 of the state, base, other value, or converted? 379 00:18:32,095 --> 00:18:36,060 380 00:18:36,060 --> 00:18:37,780 OK, someone said it, base. 381 00:18:37,780 --> 00:18:41,470 So this.state.base, that's going to be with a value 382 00:18:41,470 --> 00:18:44,980 that this select menu takes on because I want to bind to the select menu 383 00:18:44,980 --> 00:18:46,630 effectively to part of the state. 384 00:18:46,630 --> 00:18:49,990 And the part of the state that I want to connect it to is the base. 385 00:18:49,990 --> 00:18:52,180 Whatever base currency, that's the option that 386 00:18:52,180 --> 00:18:54,280 is selected in this drop-down menu. 387 00:18:54,280 --> 00:18:58,120 And likewise for the other select menu, as you might imagine, 388 00:18:58,120 --> 00:19:01,585 the value of that select menu is going to be this.state.other. 389 00:19:01,585 --> 00:19:05,830 390 00:19:05,830 --> 00:19:08,830 Now, inside of each select menu I want options. 391 00:19:08,830 --> 00:19:13,440 I want a option, a tag, for each of the possible currencies. 392 00:19:13,440 --> 00:19:15,520 And so to do that, I'm just going to go ahead 393 00:19:15,520 --> 00:19:17,460 and map over all of the currencies. 394 00:19:17,460 --> 00:19:23,165 So I can say this.currencies.map and each currency. 395 00:19:23,165 --> 00:19:24,540 So I have an array of currencies. 396 00:19:24,540 --> 00:19:29,110 I'm mapping over each one, one at a time, taking each individual currency 397 00:19:29,110 --> 00:19:30,550 and turning it into an option. 398 00:19:30,550 --> 00:19:33,300 399 00:19:33,300 --> 00:19:35,670 That option's going to show up with a text. 400 00:19:35,670 --> 00:19:39,570 Text of the option should just be the name of the currency. 401 00:19:39,570 --> 00:19:43,260 And the option needs to have a key because React requires anything 402 00:19:43,260 --> 00:19:46,380 that you iterate over to have some sort of key to uniquely identify it. 403 00:19:46,380 --> 00:19:48,660 The key you can just be the name of the currency. 404 00:19:48,660 --> 00:19:51,502 And the option also needs to have some value. 405 00:19:51,502 --> 00:19:53,460 And the value, in this case, is also just going 406 00:19:53,460 --> 00:19:55,740 to be the name of the currency. 407 00:19:55,740 --> 00:19:57,960 Because when I select an option, its value 408 00:19:57,960 --> 00:20:02,627 is going to be the new currency that I want to use. 409 00:20:02,627 --> 00:20:04,460 I can go ahead and take this code and use it 410 00:20:04,460 --> 00:20:06,937 again inside of the other select menu. 411 00:20:06,937 --> 00:20:09,020 You can imagine factoring this out into a variable 412 00:20:09,020 --> 00:20:12,030 and then inserting it to avoid redundancy. 413 00:20:12,030 --> 00:20:16,590 And so now let me go ahead and open up exchange.html. 414 00:20:16,590 --> 00:20:19,420 Now what we see is I have two drop-downs, one 415 00:20:19,420 --> 00:20:22,960 that defaults to US dollars but that shows me all the possible currencies 416 00:20:22,960 --> 00:20:26,080 I can choose from, and one that defaults to euros 417 00:20:26,080 --> 00:20:31,210 that also shows me all of the currencies that I can choose from as well. 418 00:20:31,210 --> 00:20:32,997 So all right, we're making progress. 419 00:20:32,997 --> 00:20:35,080 But of course, if I try and choose something else, 420 00:20:35,080 --> 00:20:38,620 if I try and choose Canadian dollars, for example, from this select menu, 421 00:20:38,620 --> 00:20:40,390 it stays as US dollars. 422 00:20:40,390 --> 00:20:43,540 It doesn't change because my state is never changing. 423 00:20:43,540 --> 00:20:46,870 My state is always base is US dollars and other is euros. 424 00:20:46,870 --> 00:20:50,650 So I need to have some code that says when I change the select menu, 425 00:20:50,650 --> 00:20:55,990 let's go ahead and actually make that selection so to the select menu I'll 426 00:20:55,990 --> 00:20:58,240 add in onChange handler. 427 00:20:58,240 --> 00:21:02,020 So when the select option changes, we'll go ahead and call a function. 428 00:21:02,020 --> 00:21:05,335 And I'll call it this.makeSelection. 429 00:21:05,335 --> 00:21:07,810 But you could certainly call it whatever you want. 430 00:21:07,810 --> 00:21:10,180 Likewise, when I click on another currency, 431 00:21:10,180 --> 00:21:13,990 I'll also say, when that changes, let's call this.makeSelection. 432 00:21:13,990 --> 00:21:17,010 433 00:21:17,010 --> 00:21:20,400 And now it's going to be a function I want to run. 434 00:21:20,400 --> 00:21:24,460 I'll go ahead and add a makeSelection function. 435 00:21:24,460 --> 00:21:26,440 It takes the event. 436 00:21:26,440 --> 00:21:30,380 And we're going to go ahead and update the state, this.setState. 437 00:21:30,380 --> 00:21:32,630 And what about the state needs to change? 438 00:21:32,630 --> 00:21:35,780 Well, I need to change either base or other, depending 439 00:21:35,780 --> 00:21:38,510 upon which select menu I selected. 440 00:21:38,510 --> 00:21:42,860 And the way I get at which one I selected is via this name attribute. 441 00:21:42,860 --> 00:21:46,880 The base select menu has a name attribute of base. 442 00:21:46,880 --> 00:21:50,970 And the other select menu has a name attribute of other. 443 00:21:50,970 --> 00:21:55,430 So if I want to set the state, I want to set the key of whatever event.target-- 444 00:21:55,430 --> 00:21:59,370 remember, event.target is the select menu itself-- 445 00:21:59,370 --> 00:22:02,023 whatever event.target.name is. 446 00:22:02,023 --> 00:22:03,690 If it's base, I went to update the base. 447 00:22:03,690 --> 00:22:05,770 If it's other, I want to update the other thing. 448 00:22:05,770 --> 00:22:07,740 And what do I want its value to be? 449 00:22:07,740 --> 00:22:09,960 I'll go ahead and say event.target.value. 450 00:22:09,960 --> 00:22:14,140 451 00:22:14,140 --> 00:22:17,100 So, OK, let's give this a shot. 452 00:22:17,100 --> 00:22:18,430 I refresh the page. 453 00:22:18,430 --> 00:22:19,320 I have US dollars. 454 00:22:19,320 --> 00:22:22,470 If I change it to something else, all right, it actually changes. 455 00:22:22,470 --> 00:22:26,420 If I change this one, that value changes as well. 456 00:22:26,420 --> 00:22:28,780 So I'm now able to change these select drop-downs. 457 00:22:28,780 --> 00:22:29,910 So I've got the drop-downs. 458 00:22:29,910 --> 00:22:33,650 Let me go ahead and now add the text fields. 459 00:22:33,650 --> 00:22:35,100 So I have these select menus. 460 00:22:35,100 --> 00:22:41,110 And I also want an input field, whose value is this.state.value. 461 00:22:41,110 --> 00:22:43,480 Recall that inside of our state we're storing a value 462 00:22:43,480 --> 00:22:47,110 called value, which is going to be the base currency value, 463 00:22:47,110 --> 00:22:49,150 and a value called converted, which is going 464 00:22:49,150 --> 00:22:51,990 to be the converted currency value. 465 00:22:51,990 --> 00:22:55,500 So inside this input field we're going to store this.state.value. 466 00:22:55,500 --> 00:23:00,990 And inside of the converted field, we'll go ahead and also store input, 467 00:23:00,990 --> 00:23:03,286 whose value is this.state.converted. 468 00:23:03,286 --> 00:23:05,657 469 00:23:05,657 --> 00:23:07,490 And I'm going to add an additional attribute 470 00:23:07,490 --> 00:23:10,650 to this input field called disabled. 471 00:23:10,650 --> 00:23:13,550 A disabled input field just doesn't allow you to edit it. 472 00:23:13,550 --> 00:23:17,400 I only want people to edit the top input field, not the bottom one. 473 00:23:17,400 --> 00:23:20,000 So if I said disabled equal to true, that's 474 00:23:20,000 --> 00:23:25,230 not going to allow anyone to edit the converted field, only the base currency 475 00:23:25,230 --> 00:23:25,730 field. 476 00:23:25,730 --> 00:23:28,510 477 00:23:28,510 --> 00:23:29,840 So I refreshed that. 478 00:23:29,840 --> 00:23:32,830 And great, now we have something that looks a little bit closer to what 479 00:23:32,830 --> 00:23:35,170 we might expect, whereby I have drop-downs, 480 00:23:35,170 --> 00:23:37,150 where I can choose the currency. 481 00:23:37,150 --> 00:23:38,920 I can choose a currency. 482 00:23:38,920 --> 00:23:41,200 And I have these two input fields, one of which 483 00:23:41,200 --> 00:23:44,470 I could actually type things into, and one of which is none, not changing. 484 00:23:44,470 --> 00:23:47,548 485 00:23:47,548 --> 00:23:49,840 Of course, this input field, much like the input fields 486 00:23:49,840 --> 00:23:52,570 we've seen before, if I actually try and type something into it, 487 00:23:52,570 --> 00:23:53,780 nothing's actually happening. 488 00:23:53,780 --> 00:23:55,210 It's just staying at 0. 489 00:23:55,210 --> 00:23:58,420 And the reason for that is I need to add some sort of change handler 490 00:23:58,420 --> 00:24:00,927 to say when I type something into the input field, 491 00:24:00,927 --> 00:24:03,260 we need to actually update the state of the application. 492 00:24:03,260 --> 00:24:06,160 We need to change what's inside this field. 493 00:24:06,160 --> 00:24:11,110 So on this input field I'll add onChange attribute. 494 00:24:11,110 --> 00:24:15,160 And that's going to be equal to this.changeValue. 495 00:24:15,160 --> 00:24:17,620 Again, changeValue's just an arbitrary name I'm choosing. 496 00:24:17,620 --> 00:24:20,037 But it's going to be the name of the function that's going 497 00:24:20,037 --> 00:24:21,820 to change the value of the input field. 498 00:24:21,820 --> 00:24:25,250 499 00:24:25,250 --> 00:24:28,230 So here's that changeValue function. 500 00:24:28,230 --> 00:24:32,760 And changeValue's also going to update the state. 501 00:24:32,760 --> 00:24:44,340 And it's going to set the value to event.target.value 502 00:24:44,340 --> 00:24:47,830 for updating the value inside of the state anytime 503 00:24:47,830 --> 00:24:52,250 I try and change the input field. 504 00:24:52,250 --> 00:24:54,050 So now I have an interface that works. 505 00:24:54,050 --> 00:24:56,590 I can choose different currencies from the drop-down menu. 506 00:24:56,590 --> 00:25:01,490 I can type numbers, or letters theoretically, into this input field. 507 00:25:01,490 --> 00:25:04,248 But the currency conversion isn't actually happening. 508 00:25:04,248 --> 00:25:07,040 So this is going to be the last step of actually doing the currency 509 00:25:07,040 --> 00:25:10,750 conversion when I type something into the input field. 510 00:25:10,750 --> 00:25:12,820 And so how are we going to do that? 511 00:25:12,820 --> 00:25:16,560 Well, I want some function that's going to recalculate 512 00:25:16,560 --> 00:25:20,670 the converted value based on all the information inside of my state. 513 00:25:20,670 --> 00:25:22,590 So before I do anything about the interface, 514 00:25:22,590 --> 00:25:24,510 let me just add that function. 515 00:25:24,510 --> 00:25:28,230 I'm going to add a recalculate function, which 516 00:25:28,230 --> 00:25:32,610 is going to be a function that is going to take care of the process for me 517 00:25:32,610 --> 00:25:37,050 of making the API requests to exchangeratesapi.io 518 00:25:37,050 --> 00:25:39,690 and figuring out what the exchange rate is, 519 00:25:39,690 --> 00:25:43,050 multiplying it by the amount of value that I want to convert, 520 00:25:43,050 --> 00:25:45,920 and then displaying that value on the page. 521 00:25:45,920 --> 00:25:50,560 So let me go ahead and first say this.state.value 522 00:25:50,560 --> 00:25:54,100 is the input field where I'm storing information 523 00:25:54,100 --> 00:25:58,717 about what it is that I've typed into the base currency input. 524 00:25:58,717 --> 00:26:00,800 I'm going to go ahead and parse that into a number 525 00:26:00,800 --> 00:26:02,240 because right now it's a string. 526 00:26:02,240 --> 00:26:05,450 ParseInt is a function we've seen done in order to parse an integer. 527 00:26:05,450 --> 00:26:07,280 But of course, the thing that I type into the input field 528 00:26:07,280 --> 00:26:08,250 might not be an integer. 529 00:26:08,250 --> 00:26:09,500 It could have a decimal point. 530 00:26:09,500 --> 00:26:12,330 I could be trying to convert, like, $2.80, for example. 531 00:26:12,330 --> 00:26:17,385 And so I want to say parseFloat instead of parseInt to say treat 532 00:26:17,385 --> 00:26:19,010 this number as a floating point number. 533 00:26:19,010 --> 00:26:20,718 So it's not a function we've seen before. 534 00:26:20,718 --> 00:26:25,150 It behaves basically the same way that parseInt does. 535 00:26:25,150 --> 00:26:30,290 And I'll say that inside of a variable that I'm going to call value. 536 00:26:30,290 --> 00:26:32,780 Questions so far about what I'm doing or why I'm doing it? 537 00:26:32,780 --> 00:26:36,600 538 00:26:36,600 --> 00:26:40,430 All right, there's a chance that this value is not going to be a number. 539 00:26:40,430 --> 00:26:44,650 And so there's a special value or special function in JavaScript 540 00:26:44,650 --> 00:26:50,758 called isNaN, in other words, is not a number, that takes an argument 541 00:26:50,758 --> 00:26:53,550 and just tells you whether it's a number, whether it's not a number 542 00:26:53,550 --> 00:26:54,520 or not. 543 00:26:54,520 --> 00:26:59,180 So for example, if I pass value into isNaN, 544 00:26:59,180 --> 00:27:03,640 it'll return true if value is not actually a number. 545 00:27:03,640 --> 00:27:06,460 And so that's useful for me because if it is the case 546 00:27:06,460 --> 00:27:09,150 the value is not a number, then I don't want 547 00:27:09,150 --> 00:27:11,310 to actually do any more calculation. 548 00:27:11,310 --> 00:27:12,583 I just want to return. 549 00:27:12,583 --> 00:27:13,250 We're done here. 550 00:27:13,250 --> 00:27:16,140 551 00:27:16,140 --> 00:27:20,130 So, so far, I've taken whatever I typed into the input field, tried to parse it 552 00:27:20,130 --> 00:27:23,370 as a floating point number, saved that value inside of this variable 553 00:27:23,370 --> 00:27:24,570 called value. 554 00:27:24,570 --> 00:27:27,910 And if it's not a number, then just go ahead and exit the function. 555 00:27:27,910 --> 00:27:31,600 There's nothing else that we want to do here. 556 00:27:31,600 --> 00:27:35,140 But if we keep going, if it is a number, then let me go ahead 557 00:27:35,140 --> 00:27:39,100 and run a fetch query, whereby I say OK, let's 558 00:27:39,100 --> 00:27:47,950 fetch from https://api.exchangeratesapi.io/latest. 559 00:27:47,950 --> 00:27:50,890 Base is going to be-- and then I'll plug in a value here. 560 00:27:50,890 --> 00:27:54,844 And the value I want to plug in is this.state.base. 561 00:27:54,844 --> 00:27:57,890 562 00:27:57,890 --> 00:28:00,530 Again, this code, basically the same as the JavaScript 563 00:28:00,530 --> 00:28:03,710 code that we were using before in order to do the same thing without React. 564 00:28:03,710 --> 00:28:08,240 But I'm making an API request via fetch, requesting data from a server. 565 00:28:08,240 --> 00:28:12,147 I can type in URL here to try and request data from that server. 566 00:28:12,147 --> 00:28:14,480 And right now I'm getting stuff from Exchange Rates API. 567 00:28:14,480 --> 00:28:16,897 But you could imagine getting it from something different. 568 00:28:16,897 --> 00:28:20,030 You could run a Flask web application, for instance, hosted on Heroku 569 00:28:20,030 --> 00:28:22,890 and try and fetch something from that Flask web application. 570 00:28:22,890 --> 00:28:26,000 And so here we can use the React front end to combine 571 00:28:26,000 --> 00:28:27,350 with just about any back end. 572 00:28:27,350 --> 00:28:29,570 Here I'm using the Exchange Rates API back end. 573 00:28:29,570 --> 00:28:32,360 But it could be any Flask web application that you create 574 00:28:32,360 --> 00:28:35,280 or web application server that you create in any other language. 575 00:28:35,280 --> 00:28:36,410 It doesn't really matter. 576 00:28:36,410 --> 00:28:41,670 React will just be able to request information from that back end. 577 00:28:41,670 --> 00:28:42,750 So I fetch it. 578 00:28:42,750 --> 00:28:44,967 And then the syntax here was a little bit strange. 579 00:28:44,967 --> 00:28:47,050 But you might recall that we then said, all right, 580 00:28:47,050 --> 00:28:51,630 then let's take that response and convert it to JSON. 581 00:28:51,630 --> 00:28:56,727 And then with the resulting data, do something with that data. 582 00:28:56,727 --> 00:28:57,810 Was there a question here? 583 00:28:57,810 --> 00:28:58,357 Yeah? 584 00:28:58,357 --> 00:28:59,610 AUDIENCE: [INAUDIBLE] 585 00:28:59,610 --> 00:29:03,080 SPEAKER: Yes, so these here are back ticks around the string. 586 00:29:03,080 --> 00:29:05,580 And the reason I'm using back ticks is that's how JavaScript 587 00:29:05,580 --> 00:29:10,050 does format strings, whereby if I want to insert a value into the string, 588 00:29:10,050 --> 00:29:13,710 like this.state.base, you surround the string with back ticks. 589 00:29:13,710 --> 00:29:17,790 And then you use dollar sign and curly braces to insert a value here. 590 00:29:17,790 --> 00:29:21,270 It's effectively the same as putting the lowercase f in front of a Python string 591 00:29:21,270 --> 00:29:22,299 to insert values there. 592 00:29:22,299 --> 00:29:25,257 Every language just deals with format strings a little bit differently. 593 00:29:25,257 --> 00:29:29,040 594 00:29:29,040 --> 00:29:30,580 We get back the data. 595 00:29:30,580 --> 00:29:33,950 And if we remember what the API response looks like, 596 00:29:33,950 --> 00:29:37,470 it comes back as a big JSON object that looks something like this. 597 00:29:37,470 --> 00:29:39,920 And it has a key called rates. 598 00:29:39,920 --> 00:29:43,970 And inside of that key called rates is this big object, where 599 00:29:43,970 --> 00:29:48,650 a key is going to be some currency, like New Zealand dollars. 600 00:29:48,650 --> 00:29:53,420 And the value is the exchange rate, 1.47 New Zealand dollars for every 1 US 601 00:29:53,420 --> 00:29:56,010 dollar. 602 00:29:56,010 --> 00:30:02,520 And so once I have this data inside of data.rates and then indexing 603 00:30:02,520 --> 00:30:08,330 into rates this.state.other, that's going to get for me the exchange rate, 604 00:30:08,330 --> 00:30:10,910 because the inside of data, we're going into rates. 605 00:30:10,910 --> 00:30:14,930 And inside of rates, I want whatever the other currency is. 606 00:30:14,930 --> 00:30:17,820 That's the exchange rate that I want. 607 00:30:17,820 --> 00:30:22,140 So I want to go ahead and say this.setState. 608 00:30:22,140 --> 00:30:25,620 Remember that converted was the name of the part of the state that 609 00:30:25,620 --> 00:30:30,000 referred to whatever the value of the converted dollar amount was. 610 00:30:30,000 --> 00:30:35,910 And I'm going to set converted equal to data, get at the rate, 611 00:30:35,910 --> 00:30:38,053 get at the exchange rate. 612 00:30:38,053 --> 00:30:38,970 Is this going to work? 613 00:30:38,970 --> 00:30:39,512 Is this done? 614 00:30:39,512 --> 00:30:42,460 615 00:30:42,460 --> 00:30:44,280 There's a mathematical bug here. 616 00:30:44,280 --> 00:30:49,440 617 00:30:49,440 --> 00:30:49,997 Yeah? 618 00:30:49,997 --> 00:30:53,200 AUDIENCE: You need to multiply it by [INAUDIBLE].. 619 00:30:53,200 --> 00:30:55,810 SPEAKER: Yeah, I need to multiply it by a value. 620 00:30:55,810 --> 00:30:58,480 Because if I want to convert $2, then I want 621 00:30:58,480 --> 00:31:00,430 to take whatever the exchange rate is for $1, 622 00:31:00,430 --> 00:31:03,895 and multiply it by 2 to get whatever the converted amount actually is. 623 00:31:03,895 --> 00:31:06,520 So the converted value's just going to be whatever the exchange 624 00:31:06,520 --> 00:31:10,770 rate is multiplied by the value. 625 00:31:10,770 --> 00:31:15,230 So I'm never actually calling this recalculate function anywhere, 626 00:31:15,230 --> 00:31:17,660 although this recalculate function does now hopefully 627 00:31:17,660 --> 00:31:20,090 actually work in terms of getting the exchange rate, 628 00:31:20,090 --> 00:31:24,170 multiplying it by whatever the input value is, and then updating it. 629 00:31:24,170 --> 00:31:30,440 So what I'd like to do is say, any time I change the value in the input field, 630 00:31:30,440 --> 00:31:32,382 let's go ahead and recalculate. 631 00:31:32,382 --> 00:31:34,090 And so you might imagine doing something, 632 00:31:34,090 --> 00:31:39,820 like, OK, this.setState and then this.recalculate, 633 00:31:39,820 --> 00:31:43,390 might be an easy thing to imagine as reasonable logic to do. 634 00:31:43,390 --> 00:31:47,230 Let's update the state, setting the value to event.value.target, and then 635 00:31:47,230 --> 00:31:49,310 do the recalculation. 636 00:31:49,310 --> 00:31:53,300 There's a small problem, though, in terms of the way the JavaScript works. 637 00:31:53,300 --> 00:31:56,870 A lot of JavaScript is asynchronous, meaning 638 00:31:56,870 --> 00:32:00,890 that we might be running this code, this.setState, and then 639 00:32:00,890 --> 00:32:05,300 immediately run this.recalculate, even if the state isn't yet 640 00:32:05,300 --> 00:32:06,405 done being updated. 641 00:32:06,405 --> 00:32:08,780 Like if it happens to be taking the browser a bit of time 642 00:32:08,780 --> 00:32:12,230 to update the state, this.recalculate, in theory, 643 00:32:12,230 --> 00:32:15,920 could be run before this.state is done. 644 00:32:15,920 --> 00:32:17,990 Like, this.state is going to be executed first, 645 00:32:17,990 --> 00:32:21,590 but it could take some time separately and asynchronously. 646 00:32:21,590 --> 00:32:24,800 And we might end up running this.recalculate too early. 647 00:32:24,800 --> 00:32:27,000 And so this is a common enough paradigm in React 648 00:32:27,000 --> 00:32:29,520 that there's some special syntax for doing this. 649 00:32:29,520 --> 00:32:33,600 This.setState can actually take two arguments. 650 00:32:33,600 --> 00:32:37,550 The first argument is the change that you want to make to the state. 651 00:32:37,550 --> 00:32:40,850 But you can also pass to this.setState a function 652 00:32:40,850 --> 00:32:44,880 that you want to run after the state is done updating, not something 653 00:32:44,880 --> 00:32:46,190 that we saw yesterday. 654 00:32:46,190 --> 00:32:50,150 But if I say, all right, let's set state to this new value, 655 00:32:50,150 --> 00:32:53,370 and then give this.setState another argument and say, 656 00:32:53,370 --> 00:32:59,150 all right, this.recalculate, what am effectively saying here 657 00:32:59,150 --> 00:33:02,990 is, yeah, go ahead and set the state, setting 658 00:33:02,990 --> 00:33:05,760 value equal to event.target.value. 659 00:33:05,760 --> 00:33:08,120 But when you're done setting the state, then 660 00:33:08,120 --> 00:33:10,510 run this this.recalculate function. 661 00:33:10,510 --> 00:33:14,180 And that will happen only after the state is done executing. 662 00:33:14,180 --> 00:33:16,040 So it's this optional additional argument 663 00:33:16,040 --> 00:33:20,900 I can give to this.setState to run some calculation after the state has fully 664 00:33:20,900 --> 00:33:22,283 updated. 665 00:33:22,283 --> 00:33:23,700 And so that's what I'd like to do. 666 00:33:23,700 --> 00:33:26,130 When I set the state, I'd like to recalculate 667 00:33:26,130 --> 00:33:29,160 after I've done that update. 668 00:33:29,160 --> 00:33:32,120 So let me go ahead now and refresh the page. 669 00:33:32,120 --> 00:33:33,470 And we'll give this a try. 670 00:33:33,470 --> 00:33:35,890 0 US dollars equal to 0 euros. 671 00:33:35,890 --> 00:33:40,350 I'll go ahead and delete and type in the number 1. 672 00:33:40,350 --> 00:33:43,770 And we see the number of euros corresponding to 1 US dollar. 673 00:33:43,770 --> 00:33:46,020 I type in the number 2, and I see the number 674 00:33:46,020 --> 00:33:48,600 of euros corresponding to 2 US dollars. 675 00:33:48,600 --> 00:33:50,270 Amazing. 676 00:33:50,270 --> 00:33:53,090 Where's a bug in this application? 677 00:33:53,090 --> 00:33:54,260 Not quite perfect yet. 678 00:33:54,260 --> 00:33:54,760 Yeah? 679 00:33:54,760 --> 00:33:58,555 AUDIENCE: But if you change [INAUDIBLE]. 680 00:33:58,555 --> 00:33:59,180 SPEAKER: Great. 681 00:33:59,180 --> 00:34:02,347 If I change the currency, if I say, OK, I don't want to convert doing euros, 682 00:34:02,347 --> 00:34:07,640 I want to convert between Chinese yuan, for example, and I change it, 683 00:34:07,640 --> 00:34:11,179 nothing about the input field changed. 684 00:34:11,179 --> 00:34:11,960 And why is that? 685 00:34:11,960 --> 00:34:16,850 Well, when I made a selection via this makeSelection function, 686 00:34:16,850 --> 00:34:21,170 I'm updating the state, updating the value of the drop-down. 687 00:34:21,170 --> 00:34:23,500 But I'm not doing the recalculation. 688 00:34:23,500 --> 00:34:27,590 So to fix this, I probably want to also say, after you make a selection, 689 00:34:27,590 --> 00:34:31,670 let's go ahead and also compute this.recalculate in order 690 00:34:31,670 --> 00:34:35,480 to recalculate the correct value. 691 00:34:35,480 --> 00:34:38,040 So I'll go ahead and run this again. 692 00:34:38,040 --> 00:34:40,440 0 US dollars, 0 euros. 693 00:34:40,440 --> 00:34:43,380 If I say 2 US dollars, I get that number of euros. 694 00:34:43,380 --> 00:34:47,250 If I change it to Japanese yen, then I see, OK, now we 695 00:34:47,250 --> 00:34:50,527 see an update for the number of Japanese yen that corresponded to US dollars. 696 00:34:50,527 --> 00:34:52,110 And it works the other way around too. 697 00:34:52,110 --> 00:34:54,540 I can go here and change this to Canadian dollars, 698 00:34:54,540 --> 00:34:56,940 and it changes to show me how many Japanese yen are 699 00:34:56,940 --> 00:34:58,770 equal to 2 Canadian dollars. 700 00:34:58,770 --> 00:35:01,330 701 00:35:01,330 --> 00:35:03,460 Questions about any of that and how it worked? 702 00:35:03,460 --> 00:35:08,240 703 00:35:08,240 --> 00:35:11,350 All right, a couple changes that we could theoretically make here. 704 00:35:11,350 --> 00:35:14,190 One thing is if I have 2 Canadian dollars and I delete it, 705 00:35:14,190 --> 00:35:16,570 like just turn it into the empty string, we 706 00:35:16,570 --> 00:35:20,540 end up with a situation where the number beneath stays the same. 707 00:35:20,540 --> 00:35:23,770 So you could add some logic here in order 708 00:35:23,770 --> 00:35:30,490 to try and handle this particular situation, whereby I could say, 709 00:35:30,490 --> 00:35:39,810 when I change the value of the input field, if ever the converted field-- 710 00:35:39,810 --> 00:35:43,800 I can update the converted field as well, whereby-- 711 00:35:43,800 --> 00:35:47,950 well, actually, I'll backtrack a little bit more. 712 00:35:47,950 --> 00:35:52,600 Right now what's happening is if I make a change, 713 00:35:52,600 --> 00:35:56,620 like change from 2 Canadian dollars to 22 Canadian dollars, 714 00:35:56,620 --> 00:35:59,560 there's going to be some sort of lag here, 715 00:35:59,560 --> 00:36:02,110 whereby I'm making a request to the server 716 00:36:02,110 --> 00:36:05,260 in order to make requests from the Exchange Rates API. 717 00:36:05,260 --> 00:36:07,960 And when I make that request to the Exchange Rates API, 718 00:36:07,960 --> 00:36:10,190 then it's going to update this field. 719 00:36:10,190 --> 00:36:13,060 And so what I might like to do is instead 720 00:36:13,060 --> 00:36:16,570 of just leaving the converted field as is, change it 721 00:36:16,570 --> 00:36:20,860 to something like calculating or some sort of message 722 00:36:20,860 --> 00:36:24,400 to indicate that it is calculating the exchange rate before it actually gives 723 00:36:24,400 --> 00:36:27,700 me back what the exchange rate actually is. 724 00:36:27,700 --> 00:36:30,250 And so to do this, I could do something like this. 725 00:36:30,250 --> 00:36:33,040 When I change the value of the input field, 726 00:36:33,040 --> 00:36:40,900 let me also set the value of converted equal to null, for example, meaning 727 00:36:40,900 --> 00:36:45,706 let me just clear out the value of the converted field, set it equal to null. 728 00:36:45,706 --> 00:36:48,980 And then in this input field, rather than give it 729 00:36:48,980 --> 00:36:52,160 just a value of this.state.converted, let me say 730 00:36:52,160 --> 00:36:55,880 is this.state.converted equal to null? 731 00:36:55,880 --> 00:37:00,260 If it is, then let me just say, calculating. 732 00:37:00,260 --> 00:37:02,870 But otherwise-- and again, this is the ternary operator 733 00:37:02,870 --> 00:37:04,940 that we took a look at yesterday. 734 00:37:04,940 --> 00:37:08,840 Otherwise, then it can be this.state.converted. 735 00:37:08,840 --> 00:37:11,180 So a little bit of extra logic here. 736 00:37:11,180 --> 00:37:15,110 But the logic on line 39 is saying what should show up in that lower input 737 00:37:15,110 --> 00:37:18,950 field if my converted value has null, meaning I haven't given it 738 00:37:18,950 --> 00:37:20,240 an actual number yet? 739 00:37:20,240 --> 00:37:22,690 Then go ahead and display the word calculating. 740 00:37:22,690 --> 00:37:24,830 But if there is an actual number there, then 741 00:37:24,830 --> 00:37:27,030 go ahead and just display that number. 742 00:37:27,030 --> 00:37:28,840 And so now the result is going to be-- 743 00:37:28,840 --> 00:37:31,370 and the API seems to be working rather quickly today. 744 00:37:31,370 --> 00:37:33,240 So maybe we won't be able to notice this. 745 00:37:33,240 --> 00:37:37,930 But if I type 2, and I change it to 21, yeah, there's 746 00:37:37,930 --> 00:37:39,680 a brief moment where you can see that it's 747 00:37:39,680 --> 00:37:42,980 calculating before it actually updates with what the correct answer is. 748 00:37:42,980 --> 00:37:46,100 So there's never a state where I see conflicting information 749 00:37:46,100 --> 00:37:48,380 that the other field just hasn't yet updated. 750 00:37:48,380 --> 00:37:52,290 It will always just say calculating until I've calculated the number. 751 00:37:52,290 --> 00:37:52,935 Yeah? 752 00:37:52,935 --> 00:37:56,400 AUDIENCE: [INAUDIBLE] 753 00:37:56,400 --> 00:37:57,890 754 00:37:57,890 --> 00:38:02,750 SPEAKER: This.state.converted is part of the state that represents whatever 755 00:38:02,750 --> 00:38:05,780 the value of the converted currency is. 756 00:38:05,780 --> 00:38:08,930 And I have that just because I defined it initially in the state. 757 00:38:08,930 --> 00:38:09,950 I called it converted. 758 00:38:09,950 --> 00:38:15,510 And I'm updating it whenever I want a new value for that input field. 759 00:38:15,510 --> 00:38:20,130 The only small corner case here is that now if I delete and I press Delete 760 00:38:20,130 --> 00:38:23,610 again, go to an empty input field, the other field is just 761 00:38:23,610 --> 00:38:26,040 going to say calculating forever because it's never 762 00:38:26,040 --> 00:38:27,783 going to end up getting a number. 763 00:38:27,783 --> 00:38:29,700 So you could go through and you could fix this 764 00:38:29,700 --> 00:38:31,530 by adding a couple more conditions. 765 00:38:31,530 --> 00:38:34,140 You can see the code in the source code examples 766 00:38:34,140 --> 00:38:39,360 that I posted online that'll help walk you through that as well. 767 00:38:39,360 --> 00:38:43,670 So we now have an application that can do currency conversion 768 00:38:43,670 --> 00:38:44,907 between different currencies. 769 00:38:44,907 --> 00:38:47,990 You can type in different amounts of currency and see the converted value. 770 00:38:47,990 --> 00:38:50,073 You can choose different things from the drop-down 771 00:38:50,073 --> 00:38:54,260 to convert between different currencies but there is some inefficiencies here 772 00:38:54,260 --> 00:38:54,950 still. 773 00:38:54,950 --> 00:39:04,296 Any sense for where the inefficiencies might be or room for improvement? 774 00:39:04,296 --> 00:39:10,250 775 00:39:10,250 --> 00:39:15,190 So one thing you'd might notice is that any time I change the input field, 776 00:39:15,190 --> 00:39:18,350 or anytime I select a new currency from the drop-down, 777 00:39:18,350 --> 00:39:20,680 we're running the recalculate function. 778 00:39:20,680 --> 00:39:24,430 And the recalculate function is going to parse the number, 779 00:39:24,430 --> 00:39:28,020 reach out to the API via web request, get back some response, 780 00:39:28,020 --> 00:39:32,020 parse that data, and save it inside of the input field. 781 00:39:32,020 --> 00:39:37,240 Which part of this might not be necessary to do every time I type 782 00:39:37,240 --> 00:39:39,490 something into the input field? 783 00:39:39,490 --> 00:39:39,990 Yeah? 784 00:39:39,990 --> 00:39:41,898 AUDIENCE: If you're just changing the number, 785 00:39:41,898 --> 00:39:44,760 but you're keeping the two currencies the same? 786 00:39:44,760 --> 00:39:47,990 SPEAKER: Yeah, if I'm just changing the number, 787 00:39:47,990 --> 00:39:51,920 like if I just change this from 28, press Delete, OK, now 2 US dollars, I'm 788 00:39:51,920 --> 00:39:55,040 making yet another web request to ask the API, like, 789 00:39:55,040 --> 00:39:58,370 what is the exchange rate between US dollars and euros? 790 00:39:58,370 --> 00:40:01,027 And then getting that number, which is almost definitely going 791 00:40:01,027 --> 00:40:03,110 to be the same number that I got like a second ago 792 00:40:03,110 --> 00:40:05,315 when I just did the last calculation. 793 00:40:05,315 --> 00:40:07,190 And I'm reaching out again to get that number 794 00:40:07,190 --> 00:40:09,190 and then doing something with that number, which 795 00:40:09,190 --> 00:40:11,370 is costly in a number of ways. 796 00:40:11,370 --> 00:40:13,820 It's costly on part of the this web application 797 00:40:13,820 --> 00:40:16,940 because I'm reaching out to the server when I probably don't need to. 798 00:40:16,940 --> 00:40:19,065 And it's costly on the part of the API because it's 799 00:40:19,065 --> 00:40:22,220 getting more requests than it needs to handle because there's 800 00:40:22,220 --> 00:40:24,980 some unnecessary requests here. 801 00:40:24,980 --> 00:40:27,470 Now, sure, it's possible that I typed in a number, 802 00:40:27,470 --> 00:40:30,860 and I don't type in another number until, like, tomorrow, by which point 803 00:40:30,860 --> 00:40:32,960 the currency exchange rates might change. 804 00:40:32,960 --> 00:40:37,490 But you might imagine that if I make two requests for the same exchange rate 805 00:40:37,490 --> 00:40:40,370 within, like, a minute of each other, odds 806 00:40:40,370 --> 00:40:44,300 are that it's totally fine to just use the old exchange rate 807 00:40:44,300 --> 00:40:47,840 and not have to recalculate or re-request from the API 808 00:40:47,840 --> 00:40:50,040 what the exchange rate actually is. 809 00:40:50,040 --> 00:40:52,520 And so here we're going to implement what's 810 00:40:52,520 --> 00:40:56,990 called a cache, a way that we can just store information locally rather 811 00:40:56,990 --> 00:41:00,850 than need to reach out to an API in order to access that information. 812 00:41:00,850 --> 00:41:04,100 And what we'd like to say is some sort of model, whereby we can store exchange 813 00:41:04,100 --> 00:41:06,590 rates, and if I try and request the same exchange 814 00:41:06,590 --> 00:41:10,670 rate within a minute of the last time that I requested that exchange rate, 815 00:41:10,670 --> 00:41:13,190 then don't bother making another API request. 816 00:41:13,190 --> 00:41:16,330 Just use the data that we've stored. 817 00:41:16,330 --> 00:41:17,130 Question, yeah? 818 00:41:17,130 --> 00:41:18,713 AUDIENCE: Is there a limit on the API? 819 00:41:18,713 --> 00:41:23,660 Like, if you just [INAUDIBLE] make the request every time [INAUDIBLE].. 820 00:41:23,660 --> 00:41:27,335 Is there a certain point where the API [INAUDIBLE]?? 821 00:41:27,335 --> 00:41:28,710 SPEAKER: It depends upon the API. 822 00:41:28,710 --> 00:41:31,345 Certain APIs impose formal rate limiting, 823 00:41:31,345 --> 00:41:34,470 whereby you can only make a certain number of requests per hour or per day, 824 00:41:34,470 --> 00:41:35,695 for example. 825 00:41:35,695 --> 00:41:38,820 This API happens to not be like that, though they do have a disclaimer that 826 00:41:38,820 --> 00:41:40,695 warns, like, please cache your results, which 827 00:41:40,695 --> 00:41:45,450 is what we're about to do, so as to avoid bogging them down 828 00:41:45,450 --> 00:41:49,197 with many, many requests for constant currency exchange rates. 829 00:41:49,197 --> 00:41:51,030 So it does depend a little bit upon the API. 830 00:41:51,030 --> 00:41:55,190 831 00:41:55,190 --> 00:41:57,800 Let's try and actually implement this cache. 832 00:41:57,800 --> 00:42:01,160 And you can see this implemented inside of exchange1.html, 833 00:42:01,160 --> 00:42:04,670 if you take a look at the source code examples for today. 834 00:42:04,670 --> 00:42:08,600 So up here at the top, we have this.currencies, 835 00:42:08,600 --> 00:42:10,550 and we also have this.state. 836 00:42:10,550 --> 00:42:15,140 Let me go ahead and add another variable called this.cached, 837 00:42:15,140 --> 00:42:18,290 which is going to store a JavaScript object where 838 00:42:18,290 --> 00:42:22,730 the keys are going to be currency exchange rate bases that I've stored. 839 00:42:22,730 --> 00:42:25,670 And the values are just going to be those currency exchange 840 00:42:25,670 --> 00:42:31,130 rates that I have actually stored inside of my web browser's memory, 841 00:42:31,130 --> 00:42:33,440 in this particular case. 842 00:42:33,440 --> 00:42:37,520 So all the interesting logic is not-- no longer in the interface. 843 00:42:37,520 --> 00:42:39,470 The interface is not changing at all. 844 00:42:39,470 --> 00:42:42,430 The only thing that's changing is my recalculate function. 845 00:42:42,430 --> 00:42:45,960 How am I doing this recalculation? 846 00:42:45,960 --> 00:42:50,040 Well, let me say, when I get this data back, before I set the state, 847 00:42:50,040 --> 00:42:52,090 let's update this.cached. 848 00:42:52,090 --> 00:42:55,890 Let's update what's inside of the cache, in particular 849 00:42:55,890 --> 00:43:03,340 at the key this.state.base, meaning update inside the cache. 850 00:43:03,340 --> 00:43:06,490 I need a different value in the cache for every different base currency, 851 00:43:06,490 --> 00:43:09,670 because I want to be able to store different possible base currencies. 852 00:43:09,670 --> 00:43:11,440 And I'm going to store two things. 853 00:43:11,440 --> 00:43:16,240 I'm going to store the exchange rates, which is going to be in data.rates. 854 00:43:16,240 --> 00:43:18,750 And again, this is just a JavaScript object. 855 00:43:18,750 --> 00:43:24,100 And I'm also going to store a timestamp, meaning at what time did I 856 00:43:24,100 --> 00:43:26,200 insert this data into the cache? 857 00:43:26,200 --> 00:43:28,360 At what time that I make the initial request? 858 00:43:28,360 --> 00:43:30,085 And save that data. 859 00:43:30,085 --> 00:43:31,960 And in JavaScript, there's a special function 860 00:43:31,960 --> 00:43:35,890 called date.now, which will just get us a date object that 861 00:43:35,890 --> 00:43:38,650 represent the current timestamp. 862 00:43:38,650 --> 00:43:39,800 So what's happening here? 863 00:43:39,800 --> 00:43:43,300 I'm making a request to the API, taking the resulting data, 864 00:43:43,300 --> 00:43:47,500 and storing it inside of the cache, saving it inside of some variable, 865 00:43:47,500 --> 00:43:50,890 whereby that variable is going to store the exchange rates, 866 00:43:50,890 --> 00:43:57,277 and it's also going to store the current timestamp, the timestamp for right now. 867 00:43:57,277 --> 00:43:59,110 And then we're going to go through with what 868 00:43:59,110 --> 00:44:02,530 we did before of setting the state, updating it 869 00:44:02,530 --> 00:44:05,290 to whatever they exchange rate is times the dollar amount 870 00:44:05,290 --> 00:44:07,950 that we're trying to convert. 871 00:44:07,950 --> 00:44:10,500 But now that we have this cache, we can add some logic 872 00:44:10,500 --> 00:44:13,710 before we make this API request so that we don't 873 00:44:13,710 --> 00:44:16,650 need to always make this API request. 874 00:44:16,650 --> 00:44:19,740 In particular, we can add an if statement. 875 00:44:19,740 --> 00:44:22,680 I want to check to see whether or not-- well, I 876 00:44:22,680 --> 00:44:24,130 want to check to see two things. 877 00:44:24,130 --> 00:44:28,290 One, is this base currency already in the cache? 878 00:44:28,290 --> 00:44:31,110 In which case, I don't need to make another API request. 879 00:44:31,110 --> 00:44:34,770 And if it is already in the cache, has it been less than, 880 00:44:34,770 --> 00:44:39,340 say, a minute since the last time that I made this request? 881 00:44:39,340 --> 00:44:42,358 So this is the idea of what's called cache invalidation, the idea 882 00:44:42,358 --> 00:44:44,650 that after a certain point in time, this cache is going 883 00:44:44,650 --> 00:44:47,880 to be considered stale or invalid, and I want to go ahead and make the API 884 00:44:47,880 --> 00:44:48,570 request anyway. 885 00:44:48,570 --> 00:44:50,862 If I make the-- if I check again tomorrow, 886 00:44:50,862 --> 00:44:53,070 the exchange rates are probably change, so I probably 887 00:44:53,070 --> 00:44:55,115 want to get the most up-to-date exchange rate. 888 00:44:55,115 --> 00:44:57,240 But within a certain period of time, like a minute, 889 00:44:57,240 --> 00:44:59,735 it's probably not going to change much. 890 00:44:59,735 --> 00:45:01,110 And so how am I going to do this? 891 00:45:01,110 --> 00:45:09,080 Well, if it is in the cache, it'll be in this.cached, this.state.base, right? 892 00:45:09,080 --> 00:45:11,420 This variable is the same as this. 893 00:45:11,420 --> 00:45:13,430 This is where I'm storing the information 894 00:45:13,430 --> 00:45:15,530 if it is, in fact, inside the cache. 895 00:45:15,530 --> 00:45:23,240 And let me first check to make sure it's not equal to undefined. 896 00:45:23,240 --> 00:45:26,990 If I try and index into a JavaScript object into a key that doesn't exist, 897 00:45:26,990 --> 00:45:30,140 the value I get back is a special value called undefined. 898 00:45:30,140 --> 00:45:32,240 And so if it's not equal to undefined, that 899 00:45:32,240 --> 00:45:35,060 means there's actually something in the cache. 900 00:45:35,060 --> 00:45:41,090 But I also want to make sure that it's been at most a minute 901 00:45:41,090 --> 00:45:44,280 since the last time that I updated the cache. 902 00:45:44,280 --> 00:45:46,400 And so how am I going to do that. 903 00:45:46,400 --> 00:45:50,930 Well, let's take the current timestamp, date.now, 904 00:45:50,930 --> 00:45:55,810 and let's subtract the timestamp in the cache, 905 00:45:55,810 --> 00:46:00,940 so the current timestamp minus this.cached, this.state.base-- 906 00:46:00,940 --> 00:46:02,230 that's what's in the cache-- 907 00:46:02,230 --> 00:46:07,860 dot timestamp to say get at the timestamp key 908 00:46:07,860 --> 00:46:10,680 of whatever is in the cache. 909 00:46:10,680 --> 00:46:15,600 And so I'm taking the current date, subtracting the time at which point 910 00:46:15,600 --> 00:46:18,470 I put the data in the cache. 911 00:46:18,470 --> 00:46:22,958 And as long as that is less than a minute, 912 00:46:22,958 --> 00:46:25,750 this subtraction is going to return to me a number in milliseconds. 913 00:46:25,750 --> 00:46:31,280 So a minute is going to be 1,000 milliseconds times 60 seconds. 914 00:46:31,280 --> 00:46:33,350 So long as the difference between now and when 915 00:46:33,350 --> 00:46:38,210 the time I put things in the cache is less than 1 minute, then let's go ahead 916 00:46:38,210 --> 00:46:42,880 and draw the information from the cache. 917 00:46:42,880 --> 00:46:50,650 And so to do that, we'll go ahead and say, this.setState, 918 00:46:50,650 --> 00:46:53,350 setting the converted value. 919 00:46:53,350 --> 00:46:59,640 Originally, the converted value was equal to this value, data.rates, 920 00:46:59,640 --> 00:47:02,760 this.state.other times value. 921 00:47:02,760 --> 00:47:05,910 But it's no longer going to be stored in data.rates. 922 00:47:05,910 --> 00:47:13,650 Instead of data, the information is stored in the cache, so this.cached, 923 00:47:13,650 --> 00:47:18,980 this.state.base, get at the exchange rates in the cache, 924 00:47:18,980 --> 00:47:24,100 convert it to the other currency, and multiply it by the value. 925 00:47:24,100 --> 00:47:26,140 So fair amount of code here. 926 00:47:26,140 --> 00:47:28,720 We'll zoom out, see if you can see what's going on here. 927 00:47:28,720 --> 00:47:29,720 We have a condition. 928 00:47:29,720 --> 00:47:31,390 It's running a check. 929 00:47:31,390 --> 00:47:34,630 The first part of the check is saying, is there actually 930 00:47:34,630 --> 00:47:37,240 something in the cache for this currency? 931 00:47:37,240 --> 00:47:40,720 Take the cache, look up the base currency. 932 00:47:40,720 --> 00:47:43,990 If it's undefined, there's nothing in the cache, so we can't do anything. 933 00:47:43,990 --> 00:47:47,210 So we're checking to make sure there's actually something there. 934 00:47:47,210 --> 00:47:50,690 And if there is something there, let's make sure it's recent enough to use. 935 00:47:50,690 --> 00:47:54,010 Let's take the current timestamp, subtract the time 936 00:47:54,010 --> 00:47:56,470 that we put the data in the cache, and make 937 00:47:56,470 --> 00:48:02,980 sure it's less than 1 minute, 1,000 milliseconds times 60 seconds. 938 00:48:02,980 --> 00:48:05,360 Assuming this cache is valid and we can use it, 939 00:48:05,360 --> 00:48:10,660 we'll set the state, updating the value of the converted input field 940 00:48:10,660 --> 00:48:15,160 and say, all right, let's take the value of the cache for this base currency, 941 00:48:15,160 --> 00:48:18,220 get the exchange rate for the other currency, 942 00:48:18,220 --> 00:48:22,517 and multiply it by whatever value was typed in. 943 00:48:22,517 --> 00:48:24,850 At that point, we don't need to go on with the function, 944 00:48:24,850 --> 00:48:27,340 we've already been able to update the state. 945 00:48:27,340 --> 00:48:32,821 So I can just hit Return and say exit the function now. 946 00:48:32,821 --> 00:48:34,187 A lot of code going on there. 947 00:48:34,187 --> 00:48:36,020 I encourage you to take a closer look at it. 948 00:48:36,020 --> 00:48:37,910 It's on the course website. 949 00:48:37,910 --> 00:48:41,090 And if I open up exchange.html now, the first time I 950 00:48:41,090 --> 00:48:45,350 type in currency, like 1 US dollar, it's going to calculate for a moment. 951 00:48:45,350 --> 00:48:48,193 But now if I update it, say, 12 US dollars, 952 00:48:48,193 --> 00:48:49,610 the update's almost instantaneous. 953 00:48:49,610 --> 00:48:51,527 You don't see calculating and then it changes, 954 00:48:51,527 --> 00:48:53,630 because there's no longer this additional couple 955 00:48:53,630 --> 00:48:57,770 milliseconds of latency of going to the server, requesting the exchange rates, 956 00:48:57,770 --> 00:48:59,400 and then using that information. 957 00:48:59,400 --> 00:49:01,100 It's just going to be using the cache. 958 00:49:01,100 --> 00:49:03,725 It's going to compare to whatever current value is in the cache 959 00:49:03,725 --> 00:49:05,370 to say this is within a minute. 960 00:49:05,370 --> 00:49:07,610 Let me just go ahead and update myself to go ahead 961 00:49:07,610 --> 00:49:12,540 and use the value that's stored inside of the cache. 962 00:49:12,540 --> 00:49:16,950 Questions about that idea of why we did it, of how we did it? 963 00:49:16,950 --> 00:49:23,060 964 00:49:23,060 --> 00:49:23,560 Yeah? 965 00:49:23,560 --> 00:49:28,480 AUDIENCE: Yeah, so just in terms of the syntax, I'm a little bit confused. 966 00:49:28,480 --> 00:49:33,400 When you have this.cached bracket this.state.base, bracket dot rates, 967 00:49:33,400 --> 00:49:37,010 when do you use period, and when do you use brackets when you're [INAUDIBLE]?? 968 00:49:37,010 --> 00:49:38,010 SPEAKER: Great question. 969 00:49:38,010 --> 00:49:40,802 When do you use periods when you're going into a JavaScript object? 970 00:49:40,802 --> 00:49:42,290 When do you use the brackets? 971 00:49:42,290 --> 00:49:44,930 Long story short, they're basically interchangeable, 972 00:49:44,930 --> 00:49:49,310 whereby if I go into the console here, and I have a JavaScript object-- 973 00:49:49,310 --> 00:49:50,900 I'll call it const object-- 974 00:49:50,900 --> 00:49:56,660 that has a key of A and a value of 2 and a key of B and a value of 8, 975 00:49:56,660 --> 00:50:02,030 for example, I can say object.a to get at the A property of the object. 976 00:50:02,030 --> 00:50:05,930 Or I could also say, object square bracket and then in quotation marks 977 00:50:05,930 --> 00:50:08,750 "B" to get at the B property of the object. 978 00:50:08,750 --> 00:50:10,310 And those will work the same way. 979 00:50:10,310 --> 00:50:14,300 Generally speaking, if there is a fixed name of a property of the object 980 00:50:14,300 --> 00:50:16,650 that I want, like I know it's A, for example, 981 00:50:16,650 --> 00:50:20,510 I'll just use the dot notation, object.a, to get at the A property. 982 00:50:20,510 --> 00:50:24,560 But sometimes my program doesn't know in advance what the property is. 983 00:50:24,560 --> 00:50:29,470 Like, I have some variable called key, which is set to B, for example. 984 00:50:29,470 --> 00:50:34,100 And if I want to access the key property, I can't say object.key. 985 00:50:34,100 --> 00:50:36,060 That's undefined. 986 00:50:36,060 --> 00:50:38,060 That's looking for something inside of my object 987 00:50:38,060 --> 00:50:40,250 with a key that's literally called key. 988 00:50:40,250 --> 00:50:43,520 If key is a variable and I want to look it up inside the object, 989 00:50:43,520 --> 00:50:47,490 I'll need to do object square bracket key to say, 990 00:50:47,490 --> 00:50:50,150 all right, let's get at the key property of the object. 991 00:50:50,150 --> 00:50:52,700 So you could just use square brackets for everything. 992 00:50:52,700 --> 00:50:55,617 But the dot notation sometimes just makes things a little bit cleaner. 993 00:50:55,617 --> 00:50:56,690 And so I'll use that too. 994 00:50:56,690 --> 00:50:58,940 But, yeah, good question and good clarification there. 995 00:50:58,940 --> 00:51:02,510 996 00:51:02,510 --> 00:51:03,100 Other things? 997 00:51:03,100 --> 00:51:07,050 998 00:51:07,050 --> 00:51:07,550 Yeah? 999 00:51:07,550 --> 00:51:13,102 AUDIENCE: Do you [INAUDIBLE] differences between cache and local storage? 1000 00:51:13,102 --> 00:51:14,310 SPEAKER: Yeah, good question. 1001 00:51:14,310 --> 00:51:17,143 So cache, local storage, cookies, what is the difference between all 1002 00:51:17,143 --> 00:51:17,730 these things? 1003 00:51:17,730 --> 00:51:20,390 So a cache can come in a number of different forms. 1004 00:51:20,390 --> 00:51:23,207 Your computer, CPU, has a cache that it uses 1005 00:51:23,207 --> 00:51:25,290 when it's reading things from memory, for example, 1006 00:51:25,290 --> 00:51:27,915 that is lower level than what we're dealing with in this class. 1007 00:51:27,915 --> 00:51:30,290 A cache you can think of as just a general term 1008 00:51:30,290 --> 00:51:35,570 for any way of storing data in a place that's easier to access, for instance. 1009 00:51:35,570 --> 00:51:39,980 So you might-- your web browser, for example, probably has 1010 00:51:39,980 --> 00:51:43,083 a cache for web pages, whereby when it's loading a web page, 1011 00:51:43,083 --> 00:51:45,500 it could just reload the web page that it has in the cache 1012 00:51:45,500 --> 00:51:48,350 rather than try and request the whole web page again. 1013 00:51:48,350 --> 00:51:52,630 And so caches come in many different forms, and it's a very general term. 1014 00:51:52,630 --> 00:51:54,380 The type of cache we're using here is just 1015 00:51:54,380 --> 00:51:58,070 the cache that's being stored inside of our browser's memory that's 1016 00:51:58,070 --> 00:51:59,810 going to store the exchange rates. 1017 00:51:59,810 --> 00:52:02,090 But if I were to close this page and reopen it, 1018 00:52:02,090 --> 00:52:06,350 that cache would be wiped clean because I reset the value of the cache. 1019 00:52:06,350 --> 00:52:14,420 Every time I construct a brand-new example of an app, in this case, 1020 00:52:14,420 --> 00:52:16,130 in this exchange rate program. 1021 00:52:16,130 --> 00:52:19,610 Local storage, meanwhile, you can think of as a type of cache 1022 00:52:19,610 --> 00:52:22,970 whose job it is, is to store information inside the browser, 1023 00:52:22,970 --> 00:52:27,740 in particular so that information can be used by my application 1024 00:52:27,740 --> 00:52:30,140 later if I open it up at a different time. 1025 00:52:30,140 --> 00:52:32,990 It's especially useful for being able to store information 1026 00:52:32,990 --> 00:52:36,980 inside the browser that will persist even when I close the page 1027 00:52:36,980 --> 00:52:37,700 and reopen it. 1028 00:52:37,700 --> 00:52:39,908 Because otherwise that probably wouldn't be the case. 1029 00:52:39,908 --> 00:52:43,100 And that's all happening on the client side, on the front end. 1030 00:52:43,100 --> 00:52:45,530 Cookies, meanwhile, you can think of as having 1031 00:52:45,530 --> 00:52:49,730 to do with the interaction between the server and the user, 1032 00:52:49,730 --> 00:52:52,790 the client, whereby if you have a cookie, 1033 00:52:52,790 --> 00:52:57,200 you can think of it as a way of the server keeping track of who you are, 1034 00:52:57,200 --> 00:53:01,520 such that if the user, the client, is sending a cookie along with every web 1035 00:53:01,520 --> 00:53:04,940 request it makes to the server, if the server sees that cookie multiple times, 1036 00:53:04,940 --> 00:53:09,200 it knows, OK, I know who this individual is based upon the value of the cookie, 1037 00:53:09,200 --> 00:53:11,953 for example. 1038 00:53:11,953 --> 00:53:14,120 There are also ways for cookies to store information 1039 00:53:14,120 --> 00:53:18,080 about the state of the current user's interaction with a server, 1040 00:53:18,080 --> 00:53:23,070 though we haven't really touched on that in this class. 1041 00:53:23,070 --> 00:53:23,630 Yeah? 1042 00:53:23,630 --> 00:53:24,963 AUDIENCE: Just a quick question. 1043 00:53:24,963 --> 00:53:29,130 Why would this.currencies in this.cached have their own separate variables 1044 00:53:29,130 --> 00:53:33,210 rather than including them in this.state? 1045 00:53:33,210 --> 00:53:34,450 SPEAKER: Good question. 1046 00:53:34,450 --> 00:53:37,260 So why is it that this.currencies, this.cached are separate? 1047 00:53:37,260 --> 00:53:40,080 Currencies is a separate because it's not really 1048 00:53:40,080 --> 00:53:43,980 something about the application that is going to change, 1049 00:53:43,980 --> 00:53:47,928 insofar as it's basically just a fixed list of variables. 1050 00:53:47,928 --> 00:53:50,220 I could have effectively pulled this out of it entirely 1051 00:53:50,220 --> 00:53:53,640 and just made it a constant variable inside my JavaScript, like said, 1052 00:53:53,640 --> 00:53:58,300 const currency equals something, for instance. 1053 00:53:58,300 --> 00:54:02,770 And the cache is sort of separate because nothing 1054 00:54:02,770 --> 00:54:08,140 about what the application looks like is really dependent upon the cache. 1055 00:54:08,140 --> 00:54:12,340 It's only dependent upon the values of base, other value, and converted. 1056 00:54:12,340 --> 00:54:16,240 And our recalculate function uses the cache to give converted a value. 1057 00:54:16,240 --> 00:54:19,810 But the interface itself is only based upon the value of the converted thing. 1058 00:54:19,810 --> 00:54:29,690 1059 00:54:29,690 --> 00:54:34,880 So a couple of things I'll talk about briefly, the first of which 1060 00:54:34,880 --> 00:54:37,910 is going to be options that you'll have for the morning project. 1061 00:54:37,910 --> 00:54:39,618 I'll talk about the morning project first 1062 00:54:39,618 --> 00:54:41,930 before I dive into one last example. 1063 00:54:41,930 --> 00:54:44,150 And because we are reaching-- well, actually, sorry. 1064 00:54:44,150 --> 00:54:47,150 Before I talk about the morning project, one thing that I should mention 1065 00:54:47,150 --> 00:54:50,090 is how React is typically used in practice, whereby 1066 00:54:50,090 --> 00:54:51,950 so far, when we've been writing React code, 1067 00:54:51,950 --> 00:54:56,000 we've been writing this React code purely inside of this HTML page, where 1068 00:54:56,000 --> 00:54:59,570 we've been including in the JavaScript section some JSX code, 1069 00:54:59,570 --> 00:55:02,090 JSX code being the version of JavaScript that 1070 00:55:02,090 --> 00:55:05,960 allows me to have HTML elements embedded inside the JavaScript. 1071 00:55:05,960 --> 00:55:09,110 This is not normal JavaScript code and not code 1072 00:55:09,110 --> 00:55:12,410 that our browsers natively are able to understand. 1073 00:55:12,410 --> 00:55:15,078 And this is why we've been including this Babel package up here 1074 00:55:15,078 --> 00:55:17,120 in the header section of our page, which is going 1075 00:55:17,120 --> 00:55:20,900 to take care of the job of transpiling our code from JSX 1076 00:55:20,900 --> 00:55:24,080 into plain-old JavaScript so that our browser can understand it. 1077 00:55:24,080 --> 00:55:27,350 In practice, this is not the type of program that you would want to deploy, 1078 00:55:27,350 --> 00:55:28,790 at least not in this form. 1079 00:55:28,790 --> 00:55:33,260 And in fact, when you open up any of the problems we've been doing so far, 1080 00:55:33,260 --> 00:55:37,280 you'll see this warning that says, you are using the in-browser Babel 1081 00:55:37,280 --> 00:55:38,180 transformer. 1082 00:55:38,180 --> 00:55:40,940 Be sure to pre-compile your scripts for production. 1083 00:55:40,940 --> 00:55:42,800 And what that warning is basically saying 1084 00:55:42,800 --> 00:55:48,110 is rather than deploy something that is JSX code plus the Babel 1085 00:55:48,110 --> 00:55:50,360 transformer, that's basically translating code 1086 00:55:50,360 --> 00:55:53,900 from one language to another, and have that translation process happen 1087 00:55:53,900 --> 00:55:57,350 every single time someone opens a page on your web page, 1088 00:55:57,350 --> 00:56:01,010 we can just pre-compile all of those scripts once. 1089 00:56:01,010 --> 00:56:03,380 Before we release our application for production, 1090 00:56:03,380 --> 00:56:06,170 we can say, go ahead and take all of that JSX code, 1091 00:56:06,170 --> 00:56:09,600 compile it into plain-old JavaScript code, and let's just deploy 1092 00:56:09,600 --> 00:56:10,820 the JavaScript code. 1093 00:56:10,820 --> 00:56:12,410 That way we compile it once. 1094 00:56:12,410 --> 00:56:15,770 And then anyone who uses our page can just open the page normally, 1095 00:56:15,770 --> 00:56:19,940 no translation necessary because it's already in plain-old JavaScript. 1096 00:56:19,940 --> 00:56:22,520 And so there are a number of tools for being able to do this. 1097 00:56:22,520 --> 00:56:24,710 But perhaps the most common and most popular 1098 00:56:24,710 --> 00:56:30,080 is a special program created by Facebook called Create React App. 1099 00:56:30,080 --> 00:56:32,450 In order to use Create React App, you'll need 1100 00:56:32,450 --> 00:56:36,900 to install something called Node or Node.js on your computer. 1101 00:56:36,900 --> 00:56:39,920 Node.js is just what's called at JavaScript runtime. 1102 00:56:39,920 --> 00:56:42,980 You can think of it as a way of getting JavaScript code 1103 00:56:42,980 --> 00:56:44,720 to run just about anywhere. 1104 00:56:44,720 --> 00:56:47,510 You can use JavaScript on the server, in addition 1105 00:56:47,510 --> 00:56:49,590 to using it just on the client. 1106 00:56:49,590 --> 00:56:52,100 But if you install Node.js on your computer, 1107 00:56:52,100 --> 00:56:57,260 you can then get access to a program called NPM, the Node Package Manager. 1108 00:56:57,260 --> 00:56:59,270 And there's a particular package called Create 1109 00:56:59,270 --> 00:57:03,110 React App, which is going to build for you a React app that 1110 00:57:03,110 --> 00:57:07,610 has a lot of scripts, useful scripts and tools that are already built into it. 1111 00:57:07,610 --> 00:57:10,938 And so you're not going to need this for the purposes of this class. 1112 00:57:10,938 --> 00:57:12,230 But I wanted to show it to you. 1113 00:57:12,230 --> 00:57:14,188 Because if you ever go into production in order 1114 00:57:14,188 --> 00:57:16,400 to build applications with React, you're probably 1115 00:57:16,400 --> 00:57:19,648 not going to be just putting it in the script section of your HTML page. 1116 00:57:19,648 --> 00:57:21,440 You're probably going to be doing something 1117 00:57:21,440 --> 00:57:23,100 a little more along these lines. 1118 00:57:23,100 --> 00:57:27,320 So once you install Create React App, you 1119 00:57:27,320 --> 00:57:32,720 can create a new React application by just typing create-react-app, 1120 00:57:32,720 --> 00:57:34,860 followed by the name of the application. 1121 00:57:34,860 --> 00:57:37,532 So I want to create an application called Hello. 1122 00:57:37,532 --> 00:57:40,490 And again, you're going to need to install Node and then install Create 1123 00:57:40,490 --> 00:57:42,480 React App in order for this to work. 1124 00:57:42,480 --> 00:57:45,500 But I type create-react-app Hello. 1125 00:57:45,500 --> 00:57:47,180 It's just the name of an application. 1126 00:57:47,180 --> 00:57:49,770 And then the Node package manager is going 1127 00:57:49,770 --> 00:57:53,360 to go through a long step of fetching all these packages and useful scripts 1128 00:57:53,360 --> 00:57:54,620 that it's going to use for me. 1129 00:57:54,620 --> 00:58:00,890 And it's going to build for me the basis of an application written in React. 1130 00:58:00,890 --> 00:58:04,460 And it's going to give me a starter application, basically, a foundation 1131 00:58:04,460 --> 00:58:06,410 on which I can start to build. 1132 00:58:06,410 --> 00:58:09,930 Once it's done, I'm going to CD into the Hello directory. 1133 00:58:09,930 --> 00:58:11,930 And if I type that last and look what's in here, 1134 00:58:11,930 --> 00:58:14,055 there's all sorts of stuff that's actually in here. 1135 00:58:14,055 --> 00:58:17,250 I have public, which is going to store a bunch of files 1136 00:58:17,250 --> 00:58:19,670 that our web application might use, a source folder, 1137 00:58:19,670 --> 00:58:22,340 where all the JavaScript code is actually going to be located, 1138 00:58:22,340 --> 00:58:26,203 Node modules, which is a special folder for including other packages, 1139 00:58:26,203 --> 00:58:28,370 much in the same way that in Flask we would import-- 1140 00:58:28,370 --> 00:58:31,130 in Python, we would import other modules that we might use. 1141 00:58:31,130 --> 00:58:33,530 In Node, you can also have modules that you install 1142 00:58:33,530 --> 00:58:36,400 to give you additional capabilities. 1143 00:58:36,400 --> 00:58:39,870 But once you're in here, the way to run this React application 1144 00:58:39,870 --> 00:58:46,345 is just to say NPM run start to actually start running this application. 1145 00:58:46,345 --> 00:58:49,470 And what that's going to do is it's going to start up this web application, 1146 00:58:49,470 --> 00:58:53,130 and it's going to give me a default React application that's just going 1147 00:58:53,130 --> 00:58:55,360 to display, I think, the React logo. 1148 00:58:55,360 --> 00:58:55,860 Yeah. 1149 00:58:55,860 --> 00:58:58,710 So this is the default React application that React gives you 1150 00:58:58,710 --> 00:59:01,350 if use Create React App. 1151 00:59:01,350 --> 00:59:03,845 But the nice thing about this is that it automatically 1152 00:59:03,845 --> 00:59:06,840 has separated things into files for me. 1153 00:59:06,840 --> 00:59:15,080 So that if I go into Hello and go into Source, 1154 00:59:15,080 --> 00:59:19,490 my source folder has an app.js file, where 1155 00:59:19,490 --> 00:59:23,180 they're defining an app component that, again, has a render function that 1156 00:59:23,180 --> 00:59:28,080 says editApp.js and save to reload. 1157 00:59:28,080 --> 00:59:30,620 And so this is already getting into the structure 1158 00:59:30,620 --> 00:59:32,510 of what most React applications look like, 1159 00:59:32,510 --> 00:59:34,880 which is rather than having all of the components 1160 00:59:34,880 --> 00:59:40,580 inside of the same HTML page, have a different app.js file for the app 1161 00:59:40,580 --> 00:59:44,390 component and have something else dot JS file for some other component 1162 00:59:44,390 --> 00:59:47,120 and just separate all of your components into different files. 1163 00:59:47,120 --> 00:59:49,850 It separates the CSS into different files as well 1164 00:59:49,850 --> 00:59:52,640 and just starts the process of trying to separate things out. 1165 00:59:52,640 --> 00:59:55,778 If you use Create React App, it also has dynamic reloading, 1166 00:59:55,778 --> 00:59:57,320 the way that your Flask app might do. 1167 00:59:57,320 --> 00:59:59,180 But you don't even need to refresh the page. 1168 00:59:59,180 --> 01:00:05,240 Instead of editSource.app.js and save to reload, I can replace this with Welcome 1169 01:00:05,240 --> 01:00:08,160 to CS50 Beyond and save that. 1170 01:00:08,160 --> 01:00:10,540 And without doing anything, if I just go back to Chrome, 1171 01:00:10,540 --> 01:00:13,610 my page is already updated with whatever it is that I changed. 1172 01:00:13,610 --> 01:00:15,800 So every time you save, Create React App will 1173 01:00:15,800 --> 01:00:17,930 take care of the process of auto reloading or hot 1174 01:00:17,930 --> 01:00:21,470 reloading the web page up in order to reflect whatever I've changed, so very 1175 01:00:21,470 --> 01:00:24,810 useful for development, such that you can just make a change, save it, 1176 01:00:24,810 --> 01:00:29,100 and the page will automatically reload to reflect those changes. 1177 01:00:29,100 --> 01:00:31,150 So this is very helpful for development. 1178 01:00:31,150 --> 01:00:34,500 But when I'm ready to actually build this program in order 1179 01:00:34,500 --> 01:00:36,900 to ship it, for example, I would run something 1180 01:00:36,900 --> 01:00:41,840 like NPM run build inside of my Hello directory. 1181 01:00:41,840 --> 01:00:45,600 And that's going to run a special script that Facebook has put together 1182 01:00:45,600 --> 01:00:48,600 that's going to basically take care of the process of taking all 1183 01:00:48,600 --> 01:00:51,600 this code in different files and written in JSX 1184 01:00:51,600 --> 01:00:55,620 and compile them for me into regular JavaScript 1185 01:00:55,620 --> 01:00:58,390 that any web server can understand. 1186 01:00:58,390 --> 01:01:00,570 And so if I go into the build directory now, 1187 01:01:00,570 --> 01:01:03,062 I see that I have all of these files here 1188 01:01:03,062 --> 01:01:05,520 that are basically just going to be files that I can serve, 1189 01:01:05,520 --> 01:01:08,062 using any old web server without the need to translate things 1190 01:01:08,062 --> 01:01:09,390 from one language to another. 1191 01:01:09,390 --> 01:01:10,837 And that will just work as well. 1192 01:01:10,837 --> 01:01:13,170 So not going to delve too much into that because there's 1193 01:01:13,170 --> 01:01:15,850 a lot of details and nuances here that are worth exploring, 1194 01:01:15,850 --> 01:01:17,370 and this changes from time to time. 1195 01:01:17,370 --> 01:01:19,530 But just good to be aware of, in case you 1196 01:01:19,530 --> 01:01:24,150 decide to continue with building React applications. 1197 01:01:24,150 --> 01:01:26,280 Questions before I go on about anything? 1198 01:01:26,280 --> 01:01:30,000 1199 01:01:30,000 --> 01:01:33,243 All right, so this morning's project, you're 1200 01:01:33,243 --> 01:01:34,660 going to have a number of options. 1201 01:01:34,660 --> 01:01:36,445 I'm going to introduce one of them in just a moment, 1202 01:01:36,445 --> 01:01:38,470 so we're not quite done for the morning lecture just yet. 1203 01:01:38,470 --> 01:01:40,387 But a number of options for things you can do. 1204 01:01:40,387 --> 01:01:43,178 One of the goals here is just to continue giving you an opportunity 1205 01:01:43,178 --> 01:01:44,418 to continue working on React. 1206 01:01:44,418 --> 01:01:46,960 So I know many of you are still working on or adding features 1207 01:01:46,960 --> 01:01:49,810 to your to-do list application or your flashcards application. 1208 01:01:49,810 --> 01:01:52,477 So if you'd like to, feel free to continue working on and adding 1209 01:01:52,477 --> 01:01:53,628 to those applications. 1210 01:01:53,628 --> 01:01:55,420 If you'd like an interesting new challenge, 1211 01:01:55,420 --> 01:01:57,610 if you happen to be done with those, or you're getting bored of them 1212 01:01:57,610 --> 01:01:59,443 and want to try something different, you can 1213 01:01:59,443 --> 01:02:01,330 try implementing a Connect Four game, sort 1214 01:02:01,330 --> 01:02:03,790 of an upgraded version of tic-tac-toe, this time for four 1215 01:02:03,790 --> 01:02:04,905 in a row instead of three. 1216 01:02:04,905 --> 01:02:07,280 But I'll show you what that looked like in just a moment. 1217 01:02:07,280 --> 01:02:08,230 And if you'd like to-- 1218 01:02:08,230 --> 01:02:09,400 we're on the second-to-last day now. 1219 01:02:09,400 --> 01:02:12,910 We want to give you the flexibility to explore, the freedom to try things new. 1220 01:02:12,910 --> 01:02:15,160 Feel free to start something new of your own choosing. 1221 01:02:15,160 --> 01:02:18,310 Really the goal of today is to really make the focus be about project time. 1222 01:02:18,310 --> 01:02:20,230 You've heard me talk a lot this past week. 1223 01:02:20,230 --> 01:02:21,550 So we're going to try and talk a little bit less 1224 01:02:21,550 --> 01:02:23,320 today and give you more of an opportunity 1225 01:02:23,320 --> 01:02:25,570 to really try things hands on, because you've probably 1226 01:02:25,570 --> 01:02:28,788 found by this point in time that really the best way to learn this material 1227 01:02:28,788 --> 01:02:29,830 is to be working with it. 1228 01:02:29,830 --> 01:02:30,760 Try things out. 1229 01:02:30,760 --> 01:02:34,700 Try and get features to work on your own and see what happens ultimately. 1230 01:02:34,700 --> 01:02:36,922 And so these are going to be the potential options. 1231 01:02:36,922 --> 01:02:39,880 If you choose to implement the Connect Four game, the types of features 1232 01:02:39,880 --> 01:02:42,370 you might want to consider, displaying a board 1233 01:02:42,370 --> 01:02:44,710 and which player's turn it currently is. 1234 01:02:44,710 --> 01:02:46,690 When the user clicks on a column, the turn 1235 01:02:46,690 --> 01:02:48,940 changes from red to black or black to red, 1236 01:02:48,940 --> 01:02:51,010 as the typical colors are for Connect Four. 1237 01:02:51,010 --> 01:02:55,180 If you click on a column, that drops a circle inside of that column, 1238 01:02:55,180 --> 01:02:56,278 for example. 1239 01:02:56,278 --> 01:02:58,570 Don't allow clicking on a column that's already filled, 1240 01:02:58,570 --> 01:03:01,753 if it's filled to the top of what's usually a seven-by-seven grid. 1241 01:03:01,753 --> 01:03:04,670 And when someone has four in a row, you can display who the winner is. 1242 01:03:04,670 --> 01:03:07,180 And that will probably be the last step. 1243 01:03:07,180 --> 01:03:09,932 If you choose to try and implement this project, when it's done, 1244 01:03:09,932 --> 01:03:12,640 it's probably going to look something-- it could look something-- 1245 01:03:12,640 --> 01:03:19,270 a little something like this, whereby you have a Connect Four 1246 01:03:19,270 --> 01:03:22,240 and who the current turn is in a big seven-by-seven grid. 1247 01:03:22,240 --> 01:03:24,910 And this, again, could just be an HTML table, for example. 1248 01:03:24,910 --> 01:03:28,180 I've implemented on mine some additional features 1249 01:03:28,180 --> 01:03:30,100 for detecting when the mouse is happening. 1250 01:03:30,100 --> 01:03:31,810 And there are things like onMouseEnter. 1251 01:03:31,810 --> 01:03:33,440 There's event handlers you can do for that 1252 01:03:33,440 --> 01:03:36,130 so that when you hover over columns, that you can see the column 1253 01:03:36,130 --> 01:03:38,630 highlighted, though you don't need to implement the feature, 1254 01:03:38,630 --> 01:03:40,450 at least not initially. 1255 01:03:40,450 --> 01:03:44,440 You click on a column, and, OK, that drops a red circle into that column. 1256 01:03:44,440 --> 01:03:46,030 And, OK, now it's black's turn. 1257 01:03:46,030 --> 01:03:49,660 And so black can click somewhere in order to play a black circle there. 1258 01:03:49,660 --> 01:03:54,130 And we can continue this game until someone gets four in a row. 1259 01:03:54,130 --> 01:03:58,120 And when someone gets four in a row, the winner of the game is black, 1260 01:03:58,120 --> 01:04:00,010 and we display who the winner is then. 1261 01:04:00,010 --> 01:04:01,900 So an option for something that you can try 1262 01:04:01,900 --> 01:04:04,690 to implement if you're looking for an interesting challenge. 1263 01:04:04,690 --> 01:04:08,020 And let's think about the type of state that you probably want 1264 01:04:08,020 --> 01:04:10,900 to store inside of this application. 1265 01:04:10,900 --> 01:04:12,700 What state would you want to store? 1266 01:04:12,700 --> 01:04:14,200 So even if you're not planning on programming 1267 01:04:14,200 --> 01:04:15,575 this, let's at least plan it out. 1268 01:04:15,575 --> 01:04:16,420 Think in React. 1269 01:04:16,420 --> 01:04:19,210 Think in our minds about what the state of this looks like, 1270 01:04:19,210 --> 01:04:21,640 what sort of event handlers we would need for it, 1271 01:04:21,640 --> 01:04:23,390 what is the structure this is going to be? 1272 01:04:23,390 --> 01:04:24,094 Yeah? 1273 01:04:24,094 --> 01:04:27,273 AUDIENCE: [INAUDIBLE] 1274 01:04:27,273 --> 01:04:29,440 SPEAKER: Yeah, a list of lists probably makes sense. 1275 01:04:29,440 --> 01:04:30,880 We've got a seven-by-seven grid. 1276 01:04:30,880 --> 01:04:33,088 And you have this interesting idea, which is probably 1277 01:04:33,088 --> 01:04:35,020 a good one, which is that each list might 1278 01:04:35,020 --> 01:04:38,020 want to be a list of all of the columns, like a column 1279 01:04:38,020 --> 01:04:41,290 of lists for the first column, the second column, the third column. 1280 01:04:41,290 --> 01:04:45,310 Because that's going to make it easy to implement the idea of dropping 1281 01:04:45,310 --> 01:04:48,400 a circle into one of the columns, where if we have this 1282 01:04:48,400 --> 01:04:51,220 is just like an array that is black and then red, 1283 01:04:51,220 --> 01:04:53,470 if I try and add something to this column, 1284 01:04:53,470 --> 01:04:56,980 it's as simple as just appending something to the end of that array, 1285 01:04:56,980 --> 01:04:57,610 for instance. 1286 01:04:57,610 --> 01:04:59,020 You just add to that array. 1287 01:04:59,020 --> 01:05:01,360 And that's going to result in this being reflected. 1288 01:05:01,360 --> 01:05:05,028 Now, if you design it with each column being a different array 1289 01:05:05,028 --> 01:05:07,570 inside of your application, you'll need to think a little bit 1290 01:05:07,570 --> 01:05:10,887 about how to make rows appear inside of your table, for instance. 1291 01:05:10,887 --> 01:05:12,220 But, yeah, that's good thinking. 1292 01:05:12,220 --> 01:05:15,477 So an array of arrays storing in the state 1293 01:05:15,477 --> 01:05:17,560 to store the current state of the board, what else 1294 01:05:17,560 --> 01:05:19,352 are we going to need to store in the state? 1295 01:05:19,352 --> 01:05:20,790 1296 01:05:20,790 --> 01:05:22,540 Whose turn it is, great, is it red's turn? 1297 01:05:22,540 --> 01:05:26,320 Is it a black's turn probably also something you want to store as well. 1298 01:05:26,320 --> 01:05:30,190 And what sort of event handlers do we need on this board? 1299 01:05:30,190 --> 01:05:34,600 1300 01:05:34,600 --> 01:05:36,682 How does the user interact with this page? 1301 01:05:36,682 --> 01:05:38,140 We've seen a lot of event handlers. 1302 01:05:38,140 --> 01:05:41,290 We've seen the onChange event Handler for when someone typed something 1303 01:05:41,290 --> 01:05:44,470 into an input field, for example. 1304 01:05:44,470 --> 01:05:46,730 What else have we seen that might be useful here? 1305 01:05:46,730 --> 01:05:47,710 AUDIENCE: [INAUDIBLE] 1306 01:05:47,710 --> 01:05:48,710 SPEAKER: On click, yeah. 1307 01:05:48,710 --> 01:05:50,000 And you probably want something like that, 1308 01:05:50,000 --> 01:05:52,040 that for each of these table cells, we have 1309 01:05:52,040 --> 01:05:55,680 some sort of on-click mechanism for if you click on this table cell, 1310 01:05:55,680 --> 01:05:59,065 well, that's going to correspond to dropping something in this column. 1311 01:05:59,065 --> 01:06:01,940 And there's probably no difference between clicking here and clicking 1312 01:06:01,940 --> 01:06:02,240 here. 1313 01:06:02,240 --> 01:06:04,310 Because either way, it's still clicking inside 1314 01:06:04,310 --> 01:06:06,860 of the same column, given the nature of the game. 1315 01:06:06,860 --> 01:06:09,800 And so you can think about, all right, when someone clicks on a cell, 1316 01:06:09,800 --> 01:06:13,340 you probably want to ask a question, OK, what column is it in? 1317 01:06:13,340 --> 01:06:16,820 Then you might want to ask a question like, is the column already filled? 1318 01:06:16,820 --> 01:06:19,340 In which case, well, we can't add anything more to it. 1319 01:06:19,340 --> 01:06:21,860 But if it's not already filled, then we can say something. 1320 01:06:21,860 --> 01:06:27,380 All right, let's go ahead and add something to that particular array 1321 01:06:27,380 --> 01:06:29,200 inside of our application state. 1322 01:06:29,200 --> 01:06:32,450 So these are the sorts of questions, the sorts of things to be thinking about. 1323 01:06:32,450 --> 01:06:34,825 Before you even write a single line of code, think about, 1324 01:06:34,825 --> 01:06:36,650 what are the components of the application? 1325 01:06:36,650 --> 01:06:38,780 What is the state of the application going to look like? 1326 01:06:38,780 --> 01:06:40,880 What sort of event handlers are you going to need? 1327 01:06:40,880 --> 01:06:43,810 And this is the way to begin thinking about things inside of React. 1328 01:06:43,810 --> 01:06:44,446 Yeah? 1329 01:06:44,446 --> 01:06:46,876 AUDIENCE: Is that [INAUDIBLE]? 1330 01:06:46,876 --> 01:06:50,770 Or is [INAUDIBLE]? 1331 01:06:50,770 --> 01:06:51,910 SPEAKER: Good question. 1332 01:06:51,910 --> 01:06:53,743 The way I have implemented this, and the way 1333 01:06:53,743 --> 01:06:57,190 you can certainly consider doing it, is this is just an HTML table. 1334 01:06:57,190 --> 01:07:01,540 But inside of each table cell, I've inserted an SVG target, inside 1335 01:07:01,540 --> 01:07:04,030 of which is just going to be an SVG circle. 1336 01:07:04,030 --> 01:07:06,760 And as you remember, a circle just has the center x-coordinate, 1337 01:07:06,760 --> 01:07:09,800 center y-coordinate, radius, and also a fill color. 1338 01:07:09,800 --> 01:07:13,830 And these are just fill color red and fill color black. 1339 01:07:13,830 --> 01:07:17,450 And if you really want to get fancy and implement the hover feature, 1340 01:07:17,450 --> 01:07:21,800 all the hover feature is, is when you're hovering over a column, let's go ahead 1341 01:07:21,800 --> 01:07:23,630 and turn the cells gray. 1342 01:07:23,630 --> 01:07:27,440 And if there's nothing in a cell, rather than having nothing there, 1343 01:07:27,440 --> 01:07:30,920 have a white circle instead of a red circle or a black circle. 1344 01:07:30,920 --> 01:07:33,020 And by doing that, you're able to get this effect 1345 01:07:33,020 --> 01:07:37,730 of this hover, where there's just white circles across the entire grid. 1346 01:07:37,730 --> 01:07:40,490 But when you hover over a column, the background turns gray. 1347 01:07:40,490 --> 01:07:42,560 And so you get the effect that you might expect, 1348 01:07:42,560 --> 01:07:44,477 that looks visually interesting, but really is 1349 01:07:44,477 --> 01:07:47,240 just a bunch of circles and colors changing 1350 01:07:47,240 --> 01:07:49,840 in terms of the way this is actually implemented. 1351 01:07:49,840 --> 01:07:51,840 If you're looking for a simpler version of this, 1352 01:07:51,840 --> 01:07:54,048 feel free to try and take the tic-tac-toe application 1353 01:07:54,048 --> 01:07:57,080 that we originally made in Flask and just reemployment that using React. 1354 01:07:57,080 --> 01:07:59,610 And that might be a good starting point as a place to begin 1355 01:07:59,610 --> 01:08:01,160 and then building up to something like this. 1356 01:08:01,160 --> 01:08:02,702 But there are a lot of possibilities. 1357 01:08:02,702 --> 01:08:06,170 And so goal for today is really to give you a lot of time for hands-on practice 1358 01:08:06,170 --> 01:08:07,870 in order to work on that. 1359 01:08:07,870 --> 01:08:09,740 So questions about morning project? 1360 01:08:09,740 --> 01:08:13,910 1361 01:08:13,910 --> 01:08:16,620 All right, so a couple things on a logistical note. 1362 01:08:16,620 --> 01:08:19,107 So we only have today and tomorrow left in CS50 Beyond. 1363 01:08:19,107 --> 01:08:21,899 Just see you all know, tomorrow's probably going to be a short day. 1364 01:08:21,899 --> 01:08:24,899 We're probably going to wrap up probably around mid-day 1365 01:08:24,899 --> 01:08:28,710 and not have an afternoon session tomorrow, so wrap a bit early, give you 1366 01:08:28,710 --> 01:08:32,490 most of Friday to have off in order to enjoy the weekend before classes 1367 01:08:32,490 --> 01:08:33,779 begin again on Monday. 1368 01:08:33,779 --> 01:08:36,990 And one other thing that I'd like to ask you all to do before you-- 1369 01:08:36,990 --> 01:08:39,479 right now before you actually start working on the morning 1370 01:08:39,479 --> 01:08:43,859 project is to fill out our feedback form. 1371 01:08:43,859 --> 01:08:46,990 So just try and get this some feedback before the course is over. 1372 01:08:46,990 --> 01:08:50,797 If you go to cs50.ly/feedback, you'll find an anonymous feedback form, 1373 01:08:50,797 --> 01:08:53,880 where you can leave anonymous feedback about your experience in this class 1374 01:08:53,880 --> 01:08:55,529 over the course of this week. 1375 01:08:55,529 --> 01:08:58,033 Goal for this is just very good useful data for us 1376 01:08:58,033 --> 01:08:59,950 in order to be able to help improve the class. 1377 01:08:59,950 --> 01:09:02,689 This is the first time that we are offering CS50 Beyond. 1378 01:09:02,689 --> 01:09:05,609 And so all of this is sort of brand-new curriculum and content 1379 01:09:05,609 --> 01:09:06,359 and organization. 1380 01:09:06,359 --> 01:09:09,359 So curious to get your impressions on what you think the strengths were, 1381 01:09:09,359 --> 01:09:11,279 what things you would change, or what things you would recommend 1382 01:09:11,279 --> 01:09:12,630 as improvements for the future. 1383 01:09:12,630 --> 01:09:15,240 We'll definitely read all of this feedback, and so all of it 1384 01:09:15,240 --> 01:09:16,710 would definitely be very helpful. 1385 01:09:16,710 --> 01:09:18,930 So please go ahead and fill out this feedback form. 1386 01:09:18,930 --> 01:09:20,910 When it's done, feel free to dive into your projects. 1387 01:09:20,910 --> 01:09:23,952 We'll work on these projects now in the morning, here in this auditorium, 1388 01:09:23,952 --> 01:09:26,520 until about 12:30, at which point we'll break for lunch. 1389 01:09:26,520 --> 01:09:28,687 We'll come back at 2:00 for a couple of more points, 1390 01:09:28,687 --> 01:09:31,470 but mostly to spend the afternoon focused on working on projects. 1391 01:09:31,470 --> 01:09:35,600 And so we'll break for now and let you work on those projects. 1392 01:09:35,600 --> 01:09:36,781