WEBVTT 00:00:00.000 --> 00:00:02.994 align:middle line:90% [PIANO PLAYING] 00:00:02.994 --> 00:00:11.477 align:middle line:90% 00:00:11.477 --> 00:00:14.190 align:middle line:90% SPEAKER: OK, let's get started. 00:00:14.190 --> 00:00:16.490 align:middle line:90% Welcome back, everyone, to CS50 Beyond. 00:00:16.490 --> 00:00:17.610 align:middle line:90% Our goal for today-- 00:00:17.610 --> 00:00:19.730 align:middle line:84% this is the second-to-last day of the course. 00:00:19.730 --> 00:00:21.530 align:middle line:84% And goal for today is going to be to pick up really 00:00:21.530 --> 00:00:22.700 align:middle line:90% where we left off yesterday. 00:00:22.700 --> 00:00:26.000 align:middle line:84% So yesterday we introduced a new JavaScript library called React. 00:00:26.000 --> 00:00:28.490 align:middle line:84% And React was designed to make it easier for us to build 00:00:28.490 --> 00:00:30.500 align:middle line:90% interactive and dynamic web pages. 00:00:30.500 --> 00:00:35.540 align:middle line:84% And we did so by creating components and ultimately via declarative programming, 00:00:35.540 --> 00:00:38.660 align:middle line:84% where we were describing what it is that the page should look like, 00:00:38.660 --> 00:00:42.090 align:middle line:84% whether certain variables should belong in certain places on the page, 00:00:42.090 --> 00:00:44.840 align:middle line:84% whether we should be iterating over a particular variable in order 00:00:44.840 --> 00:00:46.760 align:middle line:90% to display a list of things on the page. 00:00:46.760 --> 00:00:49.672 align:middle line:84% And then the only thing we needed to do in order to edit the page was 00:00:49.672 --> 00:00:52.130 align:middle line:84% rather than go into the dom and manipulate the dom and say, 00:00:52.130 --> 00:00:54.950 align:middle line:84% update this element or update that element, we would just say, 00:00:54.950 --> 00:00:55.970 align:middle line:90% change the data. 00:00:55.970 --> 00:00:58.610 align:middle line:84% Set the state of the component to be something different. 00:00:58.610 --> 00:01:01.010 align:middle line:84% And the page would automatically render and re-update 00:01:01.010 --> 00:01:05.400 align:middle line:84% the parts of the page that needed to in order to reflect those changes. 00:01:05.400 --> 00:01:08.570 align:middle line:84% And so the goal of today is to continue along those lines and in particular, 00:01:08.570 --> 00:01:11.338 align:middle line:84% emphasize thinking in React, thinking about how 00:01:11.338 --> 00:01:13.630 align:middle line:84% it is that we take an application that we're going for, 00:01:13.630 --> 00:01:17.012 align:middle line:84% decompose it into pieces, and then try and put it back together, such 00:01:17.012 --> 00:01:19.220 align:middle line:84% that we can figure out what components, what state we 00:01:19.220 --> 00:01:21.590 align:middle line:84% need to keep track of in order to make our applications 00:01:21.590 --> 00:01:22.910 align:middle line:90% interactive and useful. 00:01:22.910 --> 00:01:26.330 align:middle line:84% Along the way we'll talk about things like React lifecycle 00:01:26.330 --> 00:01:29.168 align:middle line:84% and about how to get your React applications, which 00:01:29.168 --> 00:01:32.210 align:middle line:84% are front-end applications, to interact with the back end, like a server, 00:01:32.210 --> 00:01:34.130 align:middle line:90% for instance, connecting to APIs then. 00:01:34.130 --> 00:01:38.100 align:middle line:84% And then we'll have some opportunity for hands-on projects, as before. 00:01:38.100 --> 00:01:41.632 align:middle line:84% And so we'll start by taking a look at an example from yesterday 00:01:41.632 --> 00:01:43.340 align:middle line:84% and begin to answer some of the questions 00:01:43.340 --> 00:01:45.905 align:middle line:90% that yesterday I pushed off until today. 00:01:45.905 --> 00:01:50.510 align:middle line:84% And so we'll take a look at counter.html And counter.html, 00:01:50.510 --> 00:01:53.240 align:middle line:84% you'll recall from yesterday, was just an application 00:01:53.240 --> 00:01:56.180 align:middle line:84% whereby it displayed a number that defaulted to the number 0. 00:01:56.180 --> 00:01:59.330 align:middle line:84% And then we had increment and decrement buttons, or plus and minus buttons, 00:01:59.330 --> 00:02:02.090 align:middle line:84% where all those buttons' data will change the value of the number. 00:02:02.090 --> 00:02:03.200 align:middle line:90% We started with 0. 00:02:03.200 --> 00:02:07.220 align:middle line:84% We can go 1, 2, 3, 4, 5 by clicking the Increment button plus the Minus button 00:02:07.220 --> 00:02:09.310 align:middle line:90% in order to go back down. 00:02:09.310 --> 00:02:11.060 align:middle line:84% And ultimately the way that we implemented 00:02:11.060 --> 00:02:19.970 align:middle line:84% that program was to say inside of counter.html, 00:02:19.970 --> 00:02:23.150 align:middle line:84% we had some state inside of our counter component 00:02:23.150 --> 00:02:26.030 align:middle line:84% that initially was just set to the number 0. 00:02:26.030 --> 00:02:29.510 align:middle line:84% And then when we click the On-click button for the plus or minus buttons, 00:02:29.510 --> 00:02:32.120 align:middle line:84% we would call the increment or decrement functions. 00:02:32.120 --> 00:02:34.620 align:middle line:84% And all those increment and decrement functions would do 00:02:34.620 --> 00:02:38.720 align:middle line:84% is call the this.setState method, which is a special method in React that 00:02:38.720 --> 00:02:41.810 align:middle line:84% takes the state and updates it, in particular by taking the count 00:02:41.810 --> 00:02:44.870 align:middle line:84% and setting it to whatever the count minus 1 is in the case of decrement, 00:02:44.870 --> 00:02:48.410 align:middle line:84% and in the case of increment, taking the count and adding 1 to it. 00:02:48.410 --> 00:02:51.230 align:middle line:84% Of course, this state only exists when this component 00:02:51.230 --> 00:02:52.920 align:middle line:90% is loaded onto the screen. 00:02:52.920 --> 00:02:54.988 align:middle line:84% And as soon as we close the page and reopen it, 00:02:54.988 --> 00:02:56.780 align:middle line:84% we're getting a brand-fresh, new component. 00:02:56.780 --> 00:02:58.620 align:middle line:90% It's remount onto the screen. 00:02:58.620 --> 00:03:03.290 align:middle line:84% And as a result, if I increase the number to, say, 5, for example, 00:03:03.290 --> 00:03:08.750 align:middle line:84% close the page, and then reopen the counter.html, we're back to 0, right? 00:03:08.750 --> 00:03:09.710 align:middle line:90% We reloaded the page. 00:03:09.710 --> 00:03:11.180 align:middle line:90% The JavaScript is rerun. 00:03:11.180 --> 00:03:15.410 align:middle line:84% And as a result, our state is reset back to the initial state 00:03:15.410 --> 00:03:20.055 align:middle line:84% as defined by the constructor, which, in this case, is the number 0. 00:03:20.055 --> 00:03:22.430 align:middle line:84% Now, before we got to the world of React and we were just 00:03:22.430 --> 00:03:26.052 align:middle line:84% dealing with plain JavaScript, how do we solve this problem, 00:03:26.052 --> 00:03:28.760 align:middle line:84% if we wanted the state to persist between when you open the page, 00:03:28.760 --> 00:03:30.052 align:middle line:90% closed the page, open it again? 00:03:30.052 --> 00:03:32.530 align:middle line:90% 00:03:32.530 --> 00:03:34.585 align:middle line:84% We cached it in a place called local storage, 00:03:34.585 --> 00:03:36.850 align:middle line:84% a place within the browser, whereby we could 00:03:36.850 --> 00:03:40.240 align:middle line:84% say I want to store the state of the application inside of local storage, 00:03:40.240 --> 00:03:44.200 align:middle line:84% such that later on in my application I can refer back to local storage 00:03:44.200 --> 00:03:49.030 align:middle line:84% and say, get this value out of local storage and put it into my application. 00:03:49.030 --> 00:03:51.640 align:middle line:84% And in React, we can do something very similar. 00:03:51.640 --> 00:03:55.360 align:middle line:84% Every React component has a number of what are called lifecycle methods, 00:03:55.360 --> 00:03:59.830 align:middle line:84% or functions that are going to run at a particular point in the component's 00:03:59.830 --> 00:04:00.800 align:middle line:90% life. 00:04:00.800 --> 00:04:03.010 align:middle line:84% And one of the most common is a special function 00:04:03.010 --> 00:04:06.512 align:middle line:90% in React called componentDidMount. 00:04:06.512 --> 00:04:07.720 align:middle line:90% There are a number of others. 00:04:07.720 --> 00:04:10.428 align:middle line:84% The only one we're going to talk about today is componentDidMount 00:04:10.428 --> 00:04:12.910 align:middle line:84% And componentDidMount is a special method in React 00:04:12.910 --> 00:04:16.810 align:middle line:84% that is going to run as soon as a component is mounted into the dom. 00:04:16.810 --> 00:04:20.360 align:middle line:84% In other words, as soon as we add this component into the dom, 00:04:20.360 --> 00:04:24.233 align:middle line:84% this is the method that's going to run before it actually ultimately renders 00:04:24.233 --> 00:04:25.900 align:middle line:90% the contents of what's going to show up. 00:04:25.900 --> 00:04:29.560 align:middle line:84% So any work we want to do of, like, setting up the component, 00:04:29.560 --> 00:04:33.500 align:middle line:90% we can do inside of componentDidMount. 00:04:33.500 --> 00:04:37.870 align:middle line:84% And so one thing we can do, for example, is get something out of local storage. 00:04:37.870 --> 00:04:44.940 align:middle line:84% I can say, local storage.getItem count in order 00:04:44.940 --> 00:04:50.600 align:middle line:84% to say, all right, let me get the count value out of local storage. 00:04:50.600 --> 00:04:55.770 align:middle line:84% And I'll save that inside of a variable that I'm just going to call count. 00:04:55.770 --> 00:04:58.130 align:middle line:84% So if there was an item called count in local storage, 00:04:58.130 --> 00:05:00.140 align:middle line:84% I'm going to extract it from local storage 00:05:00.140 --> 00:05:03.410 align:middle line:84% and save it inside of a variable called count. 00:05:03.410 --> 00:05:07.610 align:middle line:84% Now, there's a chance that there was no count item in local storage, 00:05:07.610 --> 00:05:10.080 align:middle line:84% that this is not equal to any particular value. 00:05:10.080 --> 00:05:13.430 align:middle line:84% And so it's possible that count is going to be equal to null. 00:05:13.430 --> 00:05:14.810 align:middle line:90% So let me just do a check. 00:05:14.810 --> 00:05:18.770 align:middle line:84% Let me check if count is not equal to null, 00:05:18.770 --> 00:05:23.157 align:middle line:84% meaning there actually was some count saved inside of local storage, 00:05:23.157 --> 00:05:24.990 align:middle line:84% well, then what I'm going to do is I'm going 00:05:24.990 --> 00:05:36.720 align:middle line:84% to call this.setState, setting the count equal to the result of parse int count. 00:05:36.720 --> 00:05:41.640 align:middle line:84% It's going to be stored as a string so we'll parse it as an integer 00:05:41.640 --> 00:05:45.800 align:middle line:84% in order to update the state of the application. 00:05:45.800 --> 00:05:49.010 align:middle line:84% So componentDidMount, if you think about the chronology of things, 00:05:49.010 --> 00:05:51.500 align:middle line:84% is going to happen after we've constructed this component 00:05:51.500 --> 00:05:53.450 align:middle line:90% and inserted it into the dom. 00:05:53.450 --> 00:05:55.460 align:middle line:84% And we want some initial code to be running 00:05:55.460 --> 00:05:57.710 align:middle line:84% at the beginning of this component's life, 00:05:57.710 --> 00:06:01.640 align:middle line:84% whereby we're saying from local storage, let's extract the counter variable. 00:06:01.640 --> 00:06:04.580 align:middle line:84% And as long as it's not null, then go ahead and update the state, 00:06:04.580 --> 00:06:08.150 align:middle line:84% setting count equal to the result of parsing 00:06:08.150 --> 00:06:13.600 align:middle line:84% the int of whatever the value of the count variable is. 00:06:13.600 --> 00:06:16.530 align:middle line:84% So now we have a component that can read from local storage 00:06:16.530 --> 00:06:19.461 align:middle line:84% and update its initial state based on that information. 00:06:19.461 --> 00:06:22.230 align:middle line:90% 00:06:22.230 --> 00:06:24.720 align:middle line:90% What's the missing half of this now? 00:06:24.720 --> 00:06:25.406 align:middle line:90% Yeah? 00:06:25.406 --> 00:06:29.310 align:middle line:84% AUDIENCE: [INAUDIBLE] isn't count equal to count? 00:06:29.310 --> 00:06:32.520 align:middle line:90% Why [INAUDIBLE]? 00:06:32.520 --> 00:06:34.380 align:middle line:84% SPEAKER: So the way local storage is going 00:06:34.380 --> 00:06:37.165 align:middle line:84% to store things is it's going to store the values of strings. 00:06:37.165 --> 00:06:40.290 align:middle line:84% And so that's the way that most browsers choose to implement local storage. 00:06:40.290 --> 00:06:42.250 align:middle line:84% And so when we read them from local storage, 00:06:42.250 --> 00:06:44.610 align:middle line:84% we have to assume that what's coming into us will be strings. 00:06:44.610 --> 00:06:47.568 align:middle line:84% And so we can parse them into integers in order to be able to use them. 00:06:47.568 --> 00:06:53.105 align:middle line:90% 00:06:53.105 --> 00:06:55.980 align:middle line:84% So we've got saving things-- or retrieving things from local storage. 00:06:55.980 --> 00:06:57.510 align:middle line:84% And now that I just gave away the missing piece of this 00:06:57.510 --> 00:07:01.090 align:middle line:84% is saving things into local storage, whereby we're getting the item count, 00:07:01.090 --> 00:07:02.880 align:middle line:90% but we're never setting the item count. 00:07:02.880 --> 00:07:06.450 align:middle line:84% And so we want this to happen before the window goes away. 00:07:06.450 --> 00:07:09.960 align:middle line:84% If ever I try to close the window, we want something to happen there. 00:07:09.960 --> 00:07:12.125 align:middle line:84% And so we'd like to add some sort of event listener 00:07:12.125 --> 00:07:15.365 align:middle line:84% for when I try to close the window, for example. 00:07:15.365 --> 00:07:17.490 align:middle line:84% And oftentimes you might see other web applications 00:07:17.490 --> 00:07:19.500 align:middle line:84% that have implemented something similar, whereby 00:07:19.500 --> 00:07:22.100 align:middle line:84% if you try to exit out of a web document before saving, 00:07:22.100 --> 00:07:23.850 align:middle line:84% you might get a warning message that says, 00:07:23.850 --> 00:07:26.130 align:middle line:84% are you sure you want to leave this page without saving your changes, 00:07:26.130 --> 00:07:26.730 align:middle line:90% for example. 00:07:26.730 --> 00:07:28.320 align:middle line:90% Or you haven't completed this action. 00:07:28.320 --> 00:07:29.945 align:middle line:90% Are you sure you want to do this thing? 00:07:29.945 --> 00:07:34.140 align:middle line:84% And so just in the same way that we were able to add event listeners to when 00:07:34.140 --> 00:07:36.660 align:middle line:84% the dom is done loading or when you click on a button, 00:07:36.660 --> 00:07:38.730 align:middle line:84% we can also add an event listener to the window 00:07:38.730 --> 00:07:41.610 align:middle line:84% to say, like, before this window's contents are unloaded, 00:07:41.610 --> 00:07:43.560 align:middle line:90% let's run some particular code. 00:07:43.560 --> 00:07:49.050 align:middle line:84% And so to do that, I'll say window.addEventListener. 00:07:49.050 --> 00:07:51.630 align:middle line:84% And the name of this event that we're going to be using 00:07:51.630 --> 00:07:56.040 align:middle line:90% is a special event called before unload. 00:07:56.040 --> 00:07:59.700 align:middle line:84% In other words, before this window's contents are unloaded, 00:07:59.700 --> 00:08:00.990 align:middle line:90% let's run some code. 00:08:00.990 --> 00:08:04.980 align:middle line:84% Before we get rid of this component, let's run a function. 00:08:04.980 --> 00:08:10.800 align:middle line:84% And that function is going to say local storage.setItem. 00:08:10.800 --> 00:08:13.030 align:middle line:84% And then setItem, again, takes two arguments. 00:08:13.030 --> 00:08:15.960 align:middle line:84% The first is the key, the name of the thing that we're setting. 00:08:15.960 --> 00:08:19.080 align:middle line:84% And the second is the value, what value it should take on. 00:08:19.080 --> 00:08:22.620 align:middle line:84% The key, as with line 22, we got the item with key count. 00:08:22.620 --> 00:08:26.530 align:middle line:84% So we should be setting the item with key count. 00:08:26.530 --> 00:08:27.650 align:middle line:90% And what is the value? 00:08:27.650 --> 00:08:31.502 align:middle line:90% 00:08:31.502 --> 00:08:33.210 align:middle line:84% What should we be setting count equal to? 00:08:33.210 --> 00:08:37.057 align:middle line:90% 00:08:37.057 --> 00:08:37.557 align:middle line:90% Yeah? 00:08:37.557 --> 00:08:38.682 align:middle line:90% AUDIENCE: This.state.count? 00:08:38.682 --> 00:08:40.809 align:middle line:90% SPEAKER: This.state.count, perfect. 00:08:40.809 --> 00:08:43.570 align:middle line:84% We want to set count equal to whatever the current value of count 00:08:43.570 --> 00:08:45.720 align:middle line:90% is inside of this component state. 00:08:45.720 --> 00:08:47.470 align:middle line:84% To get to this component state, we can say 00:08:47.470 --> 00:08:49.652 align:middle line:84% this.state to get at the state of the component 00:08:49.652 --> 00:08:52.360 align:middle line:84% and then dot count it to say, all right, let's go into the state, 00:08:52.360 --> 00:08:55.840 align:middle line:84% extract the thing with the key count, and use that as the value 00:08:55.840 --> 00:08:57.920 align:middle line:90% that we save into local storage. 00:08:57.920 --> 00:08:59.920 align:middle line:84% And so assuming I didn't make any mistakes here, 00:08:59.920 --> 00:09:03.090 align:middle line:84% if I go back to the page, refresh the page, 00:09:03.090 --> 00:09:06.280 align:middle line:84% I can increment the counter 1, 2, 3, 4, 5. 00:09:06.280 --> 00:09:08.610 align:middle line:84% And now if I close the counter, that's going 00:09:08.610 --> 00:09:12.900 align:middle line:84% to trigger the window.beforeUnload event, which 00:09:12.900 --> 00:09:15.620 align:middle line:84% is going to save the number 5 into local storage. 00:09:15.620 --> 00:09:20.083 align:middle line:84% And if I open counter.html again, press Return, all right, great, 00:09:20.083 --> 00:09:21.750 align:middle line:90% the component now shows me the number 5. 00:09:21.750 --> 00:09:24.930 align:middle line:84% It's been able to save that state inside of local storage, 00:09:24.930 --> 00:09:27.840 align:middle line:84% such that even when I closed the page and open it back up again, 00:09:27.840 --> 00:09:31.460 align:middle line:84% I've been able to maintain the state of the application. 00:09:31.460 --> 00:09:31.960 align:middle line:90% Yeah? 00:09:31.960 --> 00:09:35.320 align:middle line:90% AUDIENCE: [INAUDIBLE] 00:09:35.320 --> 00:09:36.672 align:middle line:90% 00:09:36.672 --> 00:09:38.380 align:middle line:84% SPEAKER: For refreshing the page as well? 00:09:38.380 --> 00:09:41.740 align:middle line:84% Yeah, if you refresh the page, if I go to 10, for example, and click Refresh, 00:09:41.740 --> 00:09:44.950 align:middle line:84% it stays at 10 because before the contents of the page 00:09:44.950 --> 00:09:49.650 align:middle line:84% are unloaded before the refresh, it's going to trigger that event listener. 00:09:49.650 --> 00:09:50.150 align:middle line:90% Yeah? 00:09:50.150 --> 00:09:52.810 align:middle line:84% AUDIENCE: Are the items that are kept in local storage-- 00:09:52.810 --> 00:09:59.030 align:middle line:84% like say you want [INAUDIBLE] the program [INAUDIBLE].. 00:09:59.030 --> 00:10:03.540 align:middle line:84% Are the items in local storage, are they secure from-- 00:10:03.540 --> 00:10:07.610 align:middle line:84% if someone hacked into your code, broke in, could they get into it? 00:10:07.610 --> 00:10:10.130 align:middle line:84% SPEAKER: The items inside of local storage 00:10:10.130 --> 00:10:12.590 align:middle line:90% are actually quite accessible to anyone. 00:10:12.590 --> 00:10:16.250 align:middle line:84% So anyone who could get access to the browser could get access to it, 00:10:16.250 --> 00:10:22.490 align:middle line:84% insofar as all I need to do is go into inspect, and I can go into, I think, 00:10:22.490 --> 00:10:25.788 align:middle line:84% it's application, at least in Chrome, and go to local storage. 00:10:25.788 --> 00:10:28.580 align:middle line:84% And over here I see a count and also a counter from a previous time 00:10:28.580 --> 00:10:30.705 align:middle line:84% that I was doing an application with local storage. 00:10:30.705 --> 00:10:32.750 align:middle line:90% So these values are highly accessible. 00:10:32.750 --> 00:10:34.260 align:middle line:90% And you can edit them as well. 00:10:34.260 --> 00:10:36.865 align:middle line:84% And so probably best not to store anything super secure inside 00:10:36.865 --> 00:10:38.240 align:middle line:90% of local storage for that reason. 00:10:38.240 --> 00:10:40.680 align:middle line:84% You'll probably want to store things on the server side. 00:10:40.680 --> 00:10:44.530 align:middle line:84% And we'll talk about interaction with server side in just a moment. 00:10:44.530 --> 00:10:45.030 align:middle line:90% Yeah? 00:10:45.030 --> 00:10:47.280 align:middle line:84% AUDIENCE: Will you let me know the website [INAUDIBLE] 00:10:47.280 --> 00:10:49.550 align:middle line:84% variables that you put in local storage [INAUDIBLE]?? 00:10:49.550 --> 00:10:52.020 align:middle line:84% SPEAKER: Local storage is domain specific. 00:10:52.020 --> 00:10:56.240 align:middle line:84% So if you have domain1.com, and you're storing things inside of local storage, 00:10:56.240 --> 00:10:59.270 align:middle line:84% domain2.com is going to have access to a different local storage. 00:10:59.270 --> 00:11:01.541 align:middle line:90% And so those are kept separate. 00:11:01.541 --> 00:11:07.360 align:middle line:84% AUDIENCE: Is there a way to make it so local pages use the same [INAUDIBLE]?? 00:11:07.360 --> 00:11:09.850 align:middle line:84% SPEAKER: So, yeah, if they're within the same domain, 00:11:09.850 --> 00:11:11.630 align:middle line:90% they can use the same local storage. 00:11:11.630 --> 00:11:14.467 align:middle line:84% For example, if I were to create another file-- 00:11:14.467 --> 00:11:15.550 align:middle line:90% and I'll just demonstrate. 00:11:15.550 --> 00:11:20.950 align:middle line:84% Like, if I just copy counter.html and call it, like, newcounter.html, 00:11:20.950 --> 00:11:24.432 align:middle line:84% which is a different file, and I open up newcounter.html, 00:11:24.432 --> 00:11:26.890 align:middle line:84% it's still going to have access to that same local storage. 00:11:26.890 --> 00:11:29.030 align:middle line:90% It still has access to the number 10. 00:11:29.030 --> 00:11:30.655 align:middle line:90% So it can draw up on those same values. 00:11:30.655 --> 00:11:36.010 align:middle line:90% 00:11:36.010 --> 00:11:37.220 align:middle line:90% Other things? 00:11:37.220 --> 00:11:37.720 align:middle line:90% Yeah? 00:11:37.720 --> 00:11:40.470 align:middle line:84% AUDIENCE: Can you just explain a little bit more of the difference 00:11:40.470 --> 00:11:45.627 align:middle line:84% between componentDidMount and why do we need didMount [INAUDIBLE]?? 00:11:45.627 --> 00:11:46.210 align:middle line:90% SPEAKER: Yeah. 00:11:46.210 --> 00:11:49.775 align:middle line:84% So componentDidMount, there are a number of what 00:11:49.775 --> 00:11:52.900 align:middle line:84% are called lifecycle methods in React, which are canonical places where you 00:11:52.900 --> 00:11:55.330 align:middle line:84% can put code, and you can guarantee that React 00:11:55.330 --> 00:11:57.890 align:middle line:84% will call upon those functions at particular times. 00:11:57.890 --> 00:12:01.660 align:middle line:84% And so in fact, so componentDidMount is one of them. 00:12:01.660 --> 00:12:03.910 align:middle line:84% ComponentWillUnmount is another one of them 00:12:03.910 --> 00:12:06.730 align:middle line:84% that React offers, which is sort of the inverse of that, 00:12:06.730 --> 00:12:10.470 align:middle line:84% which is when we're about to remove information from the dom. 00:12:10.470 --> 00:12:13.180 align:middle line:84% There's even a componentWillUpdate for whenever 00:12:13.180 --> 00:12:15.850 align:middle line:84% a component is going to refresh itself and change something 00:12:15.850 --> 00:12:16.930 align:middle line:90% about its behavior. 00:12:16.930 --> 00:12:20.000 align:middle line:84% And so there are a lot of these different lifecycle methods 00:12:20.000 --> 00:12:22.000 align:middle line:84% and more than we'll probably have time to really 00:12:22.000 --> 00:12:24.067 align:middle line:84% be able to talk about over the course of today. 00:12:24.067 --> 00:12:25.650 align:middle line:90% But I'd encourage you to look at them. 00:12:25.650 --> 00:12:27.940 align:middle line:84% There are great flow charts online of what it looks like 00:12:27.940 --> 00:12:29.523 align:middle line:90% and when different methods are called. 00:12:29.523 --> 00:12:32.140 align:middle line:84% And each one is called at a slightly different time. 00:12:32.140 --> 00:12:34.840 align:middle line:84% And so getting an understanding for when each of them are called 00:12:34.840 --> 00:12:37.030 align:middle line:84% can help you to really fine tune a component 00:12:37.030 --> 00:12:39.430 align:middle line:84% to make sure that it behaves in particular ways 00:12:39.430 --> 00:12:41.710 align:middle line:84% and only running certain code when it needs to run. 00:12:41.710 --> 00:12:46.170 align:middle line:90% 00:12:46.170 --> 00:12:47.170 align:middle line:90% So that's local storage. 00:12:47.170 --> 00:12:49.990 align:middle line:84% So a couple of people were asking about how do you save React component states, 00:12:49.990 --> 00:12:52.490 align:middle line:84% such that it's available the next time you load the program. 00:12:52.490 --> 00:12:54.170 align:middle line:90% And that's certainly one way to do it. 00:12:54.170 --> 00:12:57.400 align:middle line:84% And so far with regards to React, all of our programs 00:12:57.400 --> 00:13:01.170 align:middle line:84% have been just front-end applications, right? 00:13:01.170 --> 00:13:02.850 align:middle line:90% They just exist in the browser. 00:13:02.850 --> 00:13:04.973 align:middle line:84% There's no interaction with a back-end server, 00:13:04.973 --> 00:13:08.140 align:middle line:84% with a database, like we were doing when we were working with Flask and SQL, 00:13:08.140 --> 00:13:09.490 align:middle line:90% for example. 00:13:09.490 --> 00:13:11.830 align:middle line:84% And so there are certainly ways that we can do that. 00:13:11.830 --> 00:13:13.210 align:middle line:84% And the example that we'll use is we'll take 00:13:13.210 --> 00:13:15.210 align:middle line:84% an example that we did back when we were working 00:13:15.210 --> 00:13:18.380 align:middle line:84% and just plain JavaScript, which is that of currency conversion. 00:13:18.380 --> 00:13:23.330 align:middle line:84% So you probably recall that we had api.exchangeratesapi.io. 00:13:23.330 --> 00:13:27.580 align:middle line:84% And if I go to a particular URL, like slash latest, 00:13:27.580 --> 00:13:30.310 align:middle line:84% and then specify the base being US dollars, 00:13:30.310 --> 00:13:34.750 align:middle line:84% then I get all sorts of these different exchange rates in terms of US dollars, 00:13:34.750 --> 00:13:41.020 align:middle line:84% that one US dollar is equal to 1.3312 Canadian dollars, for example, and so 00:13:41.020 --> 00:13:42.690 align:middle line:90% on and so forth. 00:13:42.690 --> 00:13:45.610 align:middle line:84% And so what I'd like to do is create a React application 00:13:45.610 --> 00:13:48.310 align:middle line:84% that is going to be able to use these currency exchange rates. 00:13:48.310 --> 00:13:51.580 align:middle line:84% And it's going to be a fair bit more interactive than the previous one 00:13:51.580 --> 00:13:55.070 align:middle line:84% that we created was, in particular, because React 00:13:55.070 --> 00:13:58.250 align:middle line:84% is going to make it easier for us to dynamically update the page. 00:13:58.250 --> 00:14:05.000 align:middle line:84% So if I go in to exchange0.html, an application we might create 00:14:05.000 --> 00:14:07.050 align:middle line:84% is going to look a little something like this, 00:14:07.050 --> 00:14:10.400 align:middle line:84% whereby I have two drop-downs, each of which I can select a currency. 00:14:10.400 --> 00:14:11.790 align:middle line:90% This one's saying US dollars. 00:14:11.790 --> 00:14:13.880 align:middle line:84% This one's saying euros, at least for now. 00:14:13.880 --> 00:14:18.090 align:middle line:84% And I can say, all right, one US dollar is equal to that many euros. 00:14:18.090 --> 00:14:21.295 align:middle line:84% I can say, all right, 15 US dollars is equal to that many euros. 00:14:21.295 --> 00:14:24.420 align:middle line:84% And it's going to dynamically calculate for me what the exchange rates are. 00:14:24.420 --> 00:14:27.668 align:middle line:84% If I change euros to pounds, for example, 00:14:27.668 --> 00:14:30.210 align:middle line:84% it tells me the exchange rates between US dollars and pounds. 00:14:30.210 --> 00:14:33.410 align:middle line:84% And so we can get these exchange rates, much as any currency converter 00:14:33.410 --> 00:14:36.660 align:middle line:84% app that you may have used before might work, by just selecting the currencies 00:14:36.660 --> 00:14:40.890 align:middle line:84% we want, typing in into the input field what it is is the amount 00:14:40.890 --> 00:14:43.770 align:middle line:84% that we want to convert, and then see in this other field what 00:14:43.770 --> 00:14:46.750 align:middle line:90% that converted amount is equal to. 00:14:46.750 --> 00:14:50.640 align:middle line:84% And so this is the application that we're going to be building. 00:14:50.640 --> 00:14:54.480 align:middle line:90% I'll go ahead and create a new file. 00:14:54.480 --> 00:14:57.980 align:middle line:90% We'll call it exchange.html. 00:14:57.980 --> 00:15:01.700 align:middle line:84% And for now I'm going to copy the contents of counter, paste it in here, 00:15:01.700 --> 00:15:07.192 align:middle line:84% and we'll get rid of the counter component because I don't need it. 00:15:07.192 --> 00:15:09.510 align:middle line:90% I'll change the title to Exchange. 00:15:09.510 --> 00:15:12.060 align:middle line:90% 00:15:12.060 --> 00:15:16.066 align:middle line:84% And what do we need inside of our application? 00:15:16.066 --> 00:15:24.330 align:middle line:90% 00:15:24.330 --> 00:15:26.130 align:middle line:84% Any thoughts as to what type of information 00:15:26.130 --> 00:15:28.080 align:middle line:84% needs to be in the state of this application? 00:15:28.080 --> 00:15:31.680 align:middle line:84% What things can change in the application that we had before? 00:15:31.680 --> 00:15:37.632 align:middle line:90% 00:15:37.632 --> 00:15:38.630 align:middle line:90% AUDIENCE: [INAUDIBLE] 00:15:38.630 --> 00:15:40.680 align:middle line:84% SPEAKER: Yeah, the base currency that I select. 00:15:40.680 --> 00:15:43.597 align:middle line:84% So we need some sort of base currency that we're storing in the state. 00:15:43.597 --> 00:15:45.980 align:middle line:84% By default, my original application just used US dollars 00:15:45.980 --> 00:15:48.270 align:middle line:84% as the initial value of the base currency. 00:15:48.270 --> 00:15:51.200 align:middle line:84% And we also needed some way of storing the other currency, whatever 00:15:51.200 --> 00:15:53.070 align:middle line:90% else that I typed in. 00:15:53.070 --> 00:15:54.530 align:middle line:90% So go ahead and type in other. 00:15:54.530 --> 00:15:57.197 align:middle line:84% And then I think by default my application said let's make euros 00:15:57.197 --> 00:16:00.772 align:middle line:84% the other currency by default. But you can switch them up. 00:16:00.772 --> 00:16:01.730 align:middle line:90% What else could change? 00:16:01.730 --> 00:16:04.600 align:middle line:90% 00:16:04.600 --> 00:16:05.100 align:middle line:90% Yeah? 00:16:05.100 --> 00:16:06.923 align:middle line:90% AUDIENCE: The amount of base currency? 00:16:06.923 --> 00:16:09.840 align:middle line:84% SPEAKER: The amount of the base currency, yeah, so some sort of volume 00:16:09.840 --> 00:16:11.160 align:middle line:90% that initially was 0. 00:16:11.160 --> 00:16:14.740 align:middle line:84% And then there was also the converted value that was also 0 to begin with. 00:16:14.740 --> 00:16:18.240 align:middle line:84% And so I'll go ahead and create another key inside the state called converted 00:16:18.240 --> 00:16:22.000 align:middle line:90% and set that equal to 0 as well. 00:16:22.000 --> 00:16:23.970 align:middle line:90% So we have this.state. 00:16:23.970 --> 00:16:27.590 align:middle line:84% And in addition to having these currencies, the base currency 00:16:27.590 --> 00:16:29.400 align:middle line:84% and the other currency, the dropdown list 00:16:29.400 --> 00:16:31.812 align:middle line:84% also had a list of all the possible currency. 00:16:31.812 --> 00:16:34.770 align:middle line:84% That's a list that I might want to have programmatically inside my code 00:16:34.770 --> 00:16:37.380 align:middle line:84% so that it's easy to update if I ever want to add more. 00:16:37.380 --> 00:16:42.390 align:middle line:84% So for sake of example, I'm just going to add this.currencies, 00:16:42.390 --> 00:16:44.820 align:middle line:84% a new variable, just called currencies, stored 00:16:44.820 --> 00:16:46.710 align:middle line:84% inside of this component that's just going 00:16:46.710 --> 00:16:49.620 align:middle line:84% to be equal to a list of possible currencies 00:16:49.620 --> 00:16:52.320 align:middle line:84% that I want to allow people to exchange between, 00:16:52.320 --> 00:16:56.190 align:middle line:84% so maybe Australian dollars and Canadian dollars, 00:16:56.190 --> 00:16:59.220 align:middle line:84% each one just using their three letter ISO code 00:16:59.220 --> 00:17:02.000 align:middle line:84% for what the abbreviation for that currency happens to be. 00:17:02.000 --> 00:17:02.980 align:middle line:90% We'll do francs. 00:17:02.980 --> 00:17:04.349 align:middle line:90% We'll allow those. 00:17:04.349 --> 00:17:05.700 align:middle line:90% Chinese yuan we'll allow. 00:17:05.700 --> 00:17:07.500 align:middle line:90% Indian rupees we'll allow. 00:17:07.500 --> 00:17:09.460 align:middle line:90% We should do US dollars and euros. 00:17:09.460 --> 00:17:11.790 align:middle line:90% We'll do pounds, yen. 00:17:11.790 --> 00:17:14.847 align:middle line:90% And we'll also do New Zealand dollars. 00:17:14.847 --> 00:17:16.680 align:middle line:84% So there are more currencies than just this. 00:17:16.680 --> 00:17:21.880 align:middle line:84% But we'll just do a small sampling of currencies for the sake of example. 00:17:21.880 --> 00:17:27.612 align:middle line:84% Semicolon there, and, OK, we've defined the initial state of this component. 00:17:27.612 --> 00:17:29.070 align:middle line:90% And now let's render the component. 00:17:29.070 --> 00:17:32.020 align:middle line:84% What should it actually look like when we try and render it? 00:17:32.020 --> 00:17:34.020 align:middle line:84% Well, if you remember what the page looked like, 00:17:34.020 --> 00:17:36.780 align:middle line:84% there was a select menu and an input field 00:17:36.780 --> 00:17:39.300 align:middle line:84% up top for the base currency and then a select menu 00:17:39.300 --> 00:17:42.450 align:middle line:84% and an input field underneath it for the other currency. 00:17:42.450 --> 00:17:47.160 align:middle line:84% So I'll go ahead and create two divs inside of my outer div. 00:17:47.160 --> 00:17:49.810 align:middle line:84% The first of which is going to be for the base currency. 00:17:49.810 --> 00:17:52.830 align:middle line:84% And the second of which is going to be for the other currency. 00:17:52.830 --> 00:17:56.550 align:middle line:84% So the base currency is going to have a select menu. 00:17:56.550 --> 00:18:00.240 align:middle line:84% And the select menu is going to have a name of base. 00:18:00.240 --> 00:18:02.780 align:middle line:90% 00:18:02.780 --> 00:18:07.160 align:middle line:84% And for now I'll just say select name as base and slash select to end it 00:18:07.160 --> 00:18:09.060 align:middle line:90% that we'll add to this in just a moment. 00:18:09.060 --> 00:18:14.650 align:middle line:84% And in the other div, I'll have a select menu, whose name is Other. 00:18:14.650 --> 00:18:16.300 align:middle line:90% And that'll also be a select menu. 00:18:16.300 --> 00:18:21.190 align:middle line:84% So I now have a base select menu on top of another select menu. 00:18:21.190 --> 00:18:23.890 align:middle line:84% And the value of this select menu, like which 00:18:23.890 --> 00:18:29.170 align:middle line:84% item is chosen in the select menu, is going to be represented by which part 00:18:29.170 --> 00:18:32.095 align:middle line:84% of the state, base, other value, or converted? 00:18:32.095 --> 00:18:36.060 align:middle line:90% 00:18:36.060 --> 00:18:37.780 align:middle line:90% OK, someone said it, base. 00:18:37.780 --> 00:18:41.470 align:middle line:84% So this.state.base, that's going to be with a value 00:18:41.470 --> 00:18:44.980 align:middle line:84% that this select menu takes on because I want to bind to the select menu 00:18:44.980 --> 00:18:46.630 align:middle line:90% effectively to part of the state. 00:18:46.630 --> 00:18:49.990 align:middle line:84% And the part of the state that I want to connect it to is the base. 00:18:49.990 --> 00:18:52.180 align:middle line:84% Whatever base currency, that's the option that 00:18:52.180 --> 00:18:54.280 align:middle line:90% is selected in this drop-down menu. 00:18:54.280 --> 00:18:58.120 align:middle line:84% And likewise for the other select menu, as you might imagine, 00:18:58.120 --> 00:19:01.585 align:middle line:84% the value of that select menu is going to be this.state.other. 00:19:01.585 --> 00:19:05.830 align:middle line:90% 00:19:05.830 --> 00:19:08.830 align:middle line:84% Now, inside of each select menu I want options. 00:19:08.830 --> 00:19:13.440 align:middle line:84% I want a option, a tag, for each of the possible currencies. 00:19:13.440 --> 00:19:15.520 align:middle line:84% And so to do that, I'm just going to go ahead 00:19:15.520 --> 00:19:17.460 align:middle line:90% and map over all of the currencies. 00:19:17.460 --> 00:19:23.165 align:middle line:84% So I can say this.currencies.map and each currency. 00:19:23.165 --> 00:19:24.540 align:middle line:90% So I have an array of currencies. 00:19:24.540 --> 00:19:29.110 align:middle line:84% I'm mapping over each one, one at a time, taking each individual currency 00:19:29.110 --> 00:19:30.550 align:middle line:90% and turning it into an option. 00:19:30.550 --> 00:19:33.300 align:middle line:90% 00:19:33.300 --> 00:19:35.670 align:middle line:84% That option's going to show up with a text. 00:19:35.670 --> 00:19:39.570 align:middle line:84% Text of the option should just be the name of the currency. 00:19:39.570 --> 00:19:43.260 align:middle line:84% And the option needs to have a key because React requires anything 00:19:43.260 --> 00:19:46.380 align:middle line:84% that you iterate over to have some sort of key to uniquely identify it. 00:19:46.380 --> 00:19:48.660 align:middle line:84% The key you can just be the name of the currency. 00:19:48.660 --> 00:19:51.502 align:middle line:84% And the option also needs to have some value. 00:19:51.502 --> 00:19:53.460 align:middle line:84% And the value, in this case, is also just going 00:19:53.460 --> 00:19:55.740 align:middle line:90% to be the name of the currency. 00:19:55.740 --> 00:19:57.960 align:middle line:84% Because when I select an option, its value 00:19:57.960 --> 00:20:02.627 align:middle line:84% is going to be the new currency that I want to use. 00:20:02.627 --> 00:20:04.460 align:middle line:84% I can go ahead and take this code and use it 00:20:04.460 --> 00:20:06.937 align:middle line:90% again inside of the other select menu. 00:20:06.937 --> 00:20:09.020 align:middle line:84% You can imagine factoring this out into a variable 00:20:09.020 --> 00:20:12.030 align:middle line:84% and then inserting it to avoid redundancy. 00:20:12.030 --> 00:20:16.590 align:middle line:84% And so now let me go ahead and open up exchange.html. 00:20:16.590 --> 00:20:19.420 align:middle line:84% Now what we see is I have two drop-downs, one 00:20:19.420 --> 00:20:22.960 align:middle line:84% that defaults to US dollars but that shows me all the possible currencies 00:20:22.960 --> 00:20:26.080 align:middle line:84% I can choose from, and one that defaults to euros 00:20:26.080 --> 00:20:31.210 align:middle line:84% that also shows me all of the currencies that I can choose from as well. 00:20:31.210 --> 00:20:32.997 align:middle line:90% So all right, we're making progress. 00:20:32.997 --> 00:20:35.080 align:middle line:84% But of course, if I try and choose something else, 00:20:35.080 --> 00:20:38.620 align:middle line:84% if I try and choose Canadian dollars, for example, from this select menu, 00:20:38.620 --> 00:20:40.390 align:middle line:90% it stays as US dollars. 00:20:40.390 --> 00:20:43.540 align:middle line:84% It doesn't change because my state is never changing. 00:20:43.540 --> 00:20:46.870 align:middle line:84% My state is always base is US dollars and other is euros. 00:20:46.870 --> 00:20:50.650 align:middle line:84% So I need to have some code that says when I change the select menu, 00:20:50.650 --> 00:20:55.990 align:middle line:84% let's go ahead and actually make that selection so to the select menu I'll 00:20:55.990 --> 00:20:58.240 align:middle line:90% add in onChange handler. 00:20:58.240 --> 00:21:02.020 align:middle line:84% So when the select option changes, we'll go ahead and call a function. 00:21:02.020 --> 00:21:05.335 align:middle line:90% And I'll call it this.makeSelection. 00:21:05.335 --> 00:21:07.810 align:middle line:84% But you could certainly call it whatever you want. 00:21:07.810 --> 00:21:10.180 align:middle line:84% Likewise, when I click on another currency, 00:21:10.180 --> 00:21:13.990 align:middle line:84% I'll also say, when that changes, let's call this.makeSelection. 00:21:13.990 --> 00:21:17.010 align:middle line:90% 00:21:17.010 --> 00:21:20.400 align:middle line:84% And now it's going to be a function I want to run. 00:21:20.400 --> 00:21:24.460 align:middle line:84% I'll go ahead and add a makeSelection function. 00:21:24.460 --> 00:21:26.440 align:middle line:90% It takes the event. 00:21:26.440 --> 00:21:30.380 align:middle line:84% And we're going to go ahead and update the state, this.setState. 00:21:30.380 --> 00:21:32.630 align:middle line:84% And what about the state needs to change? 00:21:32.630 --> 00:21:35.780 align:middle line:84% Well, I need to change either base or other, depending 00:21:35.780 --> 00:21:38.510 align:middle line:90% upon which select menu I selected. 00:21:38.510 --> 00:21:42.860 align:middle line:84% And the way I get at which one I selected is via this name attribute. 00:21:42.860 --> 00:21:46.880 align:middle line:84% The base select menu has a name attribute of base. 00:21:46.880 --> 00:21:50.970 align:middle line:84% And the other select menu has a name attribute of other. 00:21:50.970 --> 00:21:55.430 align:middle line:84% So if I want to set the state, I want to set the key of whatever event.target-- 00:21:55.430 --> 00:21:59.370 align:middle line:84% remember, event.target is the select menu itself-- 00:21:59.370 --> 00:22:02.023 align:middle line:90% whatever event.target.name is. 00:22:02.023 --> 00:22:03.690 align:middle line:90% If it's base, I went to update the base. 00:22:03.690 --> 00:22:05.770 align:middle line:84% If it's other, I want to update the other thing. 00:22:05.770 --> 00:22:07.740 align:middle line:90% And what do I want its value to be? 00:22:07.740 --> 00:22:09.960 align:middle line:84% I'll go ahead and say event.target.value. 00:22:09.960 --> 00:22:14.140 align:middle line:90% 00:22:14.140 --> 00:22:17.100 align:middle line:90% So, OK, let's give this a shot. 00:22:17.100 --> 00:22:18.430 align:middle line:90% I refresh the page. 00:22:18.430 --> 00:22:19.320 align:middle line:90% I have US dollars. 00:22:19.320 --> 00:22:22.470 align:middle line:84% If I change it to something else, all right, it actually changes. 00:22:22.470 --> 00:22:26.420 align:middle line:84% If I change this one, that value changes as well. 00:22:26.420 --> 00:22:28.780 align:middle line:84% So I'm now able to change these select drop-downs. 00:22:28.780 --> 00:22:29.910 align:middle line:90% So I've got the drop-downs. 00:22:29.910 --> 00:22:33.650 align:middle line:84% Let me go ahead and now add the text fields. 00:22:33.650 --> 00:22:35.100 align:middle line:90% So I have these select menus. 00:22:35.100 --> 00:22:41.110 align:middle line:84% And I also want an input field, whose value is this.state.value. 00:22:41.110 --> 00:22:43.480 align:middle line:84% Recall that inside of our state we're storing a value 00:22:43.480 --> 00:22:47.110 align:middle line:84% called value, which is going to be the base currency value, 00:22:47.110 --> 00:22:49.150 align:middle line:84% and a value called converted, which is going 00:22:49.150 --> 00:22:51.990 align:middle line:90% to be the converted currency value. 00:22:51.990 --> 00:22:55.500 align:middle line:84% So inside this input field we're going to store this.state.value. 00:22:55.500 --> 00:23:00.990 align:middle line:84% And inside of the converted field, we'll go ahead and also store input, 00:23:00.990 --> 00:23:03.286 align:middle line:90% whose value is this.state.converted. 00:23:03.286 --> 00:23:05.657 align:middle line:90% 00:23:05.657 --> 00:23:07.490 align:middle line:84% And I'm going to add an additional attribute 00:23:07.490 --> 00:23:10.650 align:middle line:90% to this input field called disabled. 00:23:10.650 --> 00:23:13.550 align:middle line:84% A disabled input field just doesn't allow you to edit it. 00:23:13.550 --> 00:23:17.400 align:middle line:84% I only want people to edit the top input field, not the bottom one. 00:23:17.400 --> 00:23:20.000 align:middle line:84% So if I said disabled equal to true, that's 00:23:20.000 --> 00:23:25.230 align:middle line:84% not going to allow anyone to edit the converted field, only the base currency 00:23:25.230 --> 00:23:25.730 align:middle line:90% field. 00:23:25.730 --> 00:23:28.510 align:middle line:90% 00:23:28.510 --> 00:23:29.840 align:middle line:90% So I refreshed that. 00:23:29.840 --> 00:23:32.830 align:middle line:84% And great, now we have something that looks a little bit closer to what 00:23:32.830 --> 00:23:35.170 align:middle line:84% we might expect, whereby I have drop-downs, 00:23:35.170 --> 00:23:37.150 align:middle line:90% where I can choose the currency. 00:23:37.150 --> 00:23:38.920 align:middle line:90% I can choose a currency. 00:23:38.920 --> 00:23:41.200 align:middle line:84% And I have these two input fields, one of which 00:23:41.200 --> 00:23:44.470 align:middle line:84% I could actually type things into, and one of which is none, not changing. 00:23:44.470 --> 00:23:47.548 align:middle line:90% 00:23:47.548 --> 00:23:49.840 align:middle line:84% Of course, this input field, much like the input fields 00:23:49.840 --> 00:23:52.570 align:middle line:84% we've seen before, if I actually try and type something into it, 00:23:52.570 --> 00:23:53.780 align:middle line:90% nothing's actually happening. 00:23:53.780 --> 00:23:55.210 align:middle line:90% It's just staying at 0. 00:23:55.210 --> 00:23:58.420 align:middle line:84% And the reason for that is I need to add some sort of change handler 00:23:58.420 --> 00:24:00.927 align:middle line:84% to say when I type something into the input field, 00:24:00.927 --> 00:24:03.260 align:middle line:84% we need to actually update the state of the application. 00:24:03.260 --> 00:24:06.160 align:middle line:84% We need to change what's inside this field. 00:24:06.160 --> 00:24:11.110 align:middle line:84% So on this input field I'll add onChange attribute. 00:24:11.110 --> 00:24:15.160 align:middle line:84% And that's going to be equal to this.changeValue. 00:24:15.160 --> 00:24:17.620 align:middle line:84% Again, changeValue's just an arbitrary name I'm choosing. 00:24:17.620 --> 00:24:20.037 align:middle line:84% But it's going to be the name of the function that's going 00:24:20.037 --> 00:24:21.820 align:middle line:90% to change the value of the input field. 00:24:21.820 --> 00:24:25.250 align:middle line:90% 00:24:25.250 --> 00:24:28.230 align:middle line:90% So here's that changeValue function. 00:24:28.230 --> 00:24:32.760 align:middle line:84% And changeValue's also going to update the state. 00:24:32.760 --> 00:24:44.340 align:middle line:84% And it's going to set the value to event.target.value 00:24:44.340 --> 00:24:47.830 align:middle line:84% for updating the value inside of the state anytime 00:24:47.830 --> 00:24:52.250 align:middle line:90% I try and change the input field. 00:24:52.250 --> 00:24:54.050 align:middle line:90% So now I have an interface that works. 00:24:54.050 --> 00:24:56.590 align:middle line:84% I can choose different currencies from the drop-down menu. 00:24:56.590 --> 00:25:01.490 align:middle line:84% I can type numbers, or letters theoretically, into this input field. 00:25:01.490 --> 00:25:04.248 align:middle line:84% But the currency conversion isn't actually happening. 00:25:04.248 --> 00:25:07.040 align:middle line:84% So this is going to be the last step of actually doing the currency 00:25:07.040 --> 00:25:10.750 align:middle line:84% conversion when I type something into the input field. 00:25:10.750 --> 00:25:12.820 align:middle line:90% And so how are we going to do that? 00:25:12.820 --> 00:25:16.560 align:middle line:84% Well, I want some function that's going to recalculate 00:25:16.560 --> 00:25:20.670 align:middle line:84% the converted value based on all the information inside of my state. 00:25:20.670 --> 00:25:22.590 align:middle line:84% So before I do anything about the interface, 00:25:22.590 --> 00:25:24.510 align:middle line:90% let me just add that function. 00:25:24.510 --> 00:25:28.230 align:middle line:84% I'm going to add a recalculate function, which 00:25:28.230 --> 00:25:32.610 align:middle line:84% is going to be a function that is going to take care of the process for me 00:25:32.610 --> 00:25:37.050 align:middle line:84% of making the API requests to exchangeratesapi.io 00:25:37.050 --> 00:25:39.690 align:middle line:84% and figuring out what the exchange rate is, 00:25:39.690 --> 00:25:43.050 align:middle line:84% multiplying it by the amount of value that I want to convert, 00:25:43.050 --> 00:25:45.920 align:middle line:84% and then displaying that value on the page. 00:25:45.920 --> 00:25:50.560 align:middle line:84% So let me go ahead and first say this.state.value 00:25:50.560 --> 00:25:54.100 align:middle line:84% is the input field where I'm storing information 00:25:54.100 --> 00:25:58.717 align:middle line:84% about what it is that I've typed into the base currency input. 00:25:58.717 --> 00:26:00.800 align:middle line:84% I'm going to go ahead and parse that into a number 00:26:00.800 --> 00:26:02.240 align:middle line:90% because right now it's a string. 00:26:02.240 --> 00:26:05.450 align:middle line:84% ParseInt is a function we've seen done in order to parse an integer. 00:26:05.450 --> 00:26:07.280 align:middle line:84% But of course, the thing that I type into the input field 00:26:07.280 --> 00:26:08.250 align:middle line:90% might not be an integer. 00:26:08.250 --> 00:26:09.500 align:middle line:90% It could have a decimal point. 00:26:09.500 --> 00:26:12.330 align:middle line:84% I could be trying to convert, like, $2.80, for example. 00:26:12.330 --> 00:26:17.385 align:middle line:84% And so I want to say parseFloat instead of parseInt to say treat 00:26:17.385 --> 00:26:19.010 align:middle line:90% this number as a floating point number. 00:26:19.010 --> 00:26:20.718 align:middle line:84% So it's not a function we've seen before. 00:26:20.718 --> 00:26:25.150 align:middle line:84% It behaves basically the same way that parseInt does. 00:26:25.150 --> 00:26:30.290 align:middle line:84% And I'll say that inside of a variable that I'm going to call value. 00:26:30.290 --> 00:26:32.780 align:middle line:84% Questions so far about what I'm doing or why I'm doing it? 00:26:32.780 --> 00:26:36.600 align:middle line:90% 00:26:36.600 --> 00:26:40.430 align:middle line:84% All right, there's a chance that this value is not going to be a number. 00:26:40.430 --> 00:26:44.650 align:middle line:84% And so there's a special value or special function in JavaScript 00:26:44.650 --> 00:26:50.758 align:middle line:84% called isNaN, in other words, is not a number, that takes an argument 00:26:50.758 --> 00:26:53.550 align:middle line:84% and just tells you whether it's a number, whether it's not a number 00:26:53.550 --> 00:26:54.520 align:middle line:90% or not. 00:26:54.520 --> 00:26:59.180 align:middle line:84% So for example, if I pass value into isNaN, 00:26:59.180 --> 00:27:03.640 align:middle line:84% it'll return true if value is not actually a number. 00:27:03.640 --> 00:27:06.460 align:middle line:84% And so that's useful for me because if it is the case 00:27:06.460 --> 00:27:09.150 align:middle line:84% the value is not a number, then I don't want 00:27:09.150 --> 00:27:11.310 align:middle line:90% to actually do any more calculation. 00:27:11.310 --> 00:27:12.583 align:middle line:90% I just want to return. 00:27:12.583 --> 00:27:13.250 align:middle line:90% We're done here. 00:27:13.250 --> 00:27:16.140 align:middle line:90% 00:27:16.140 --> 00:27:20.130 align:middle line:84% So, so far, I've taken whatever I typed into the input field, tried to parse it 00:27:20.130 --> 00:27:23.370 align:middle line:84% as a floating point number, saved that value inside of this variable 00:27:23.370 --> 00:27:24.570 align:middle line:90% called value. 00:27:24.570 --> 00:27:27.910 align:middle line:84% And if it's not a number, then just go ahead and exit the function. 00:27:27.910 --> 00:27:31.600 align:middle line:84% There's nothing else that we want to do here. 00:27:31.600 --> 00:27:35.140 align:middle line:84% But if we keep going, if it is a number, then let me go ahead 00:27:35.140 --> 00:27:39.100 align:middle line:84% and run a fetch query, whereby I say OK, let's 00:27:39.100 --> 00:27:47.950 align:middle line:84% fetch from https://api.exchangeratesapi.io/latest. 00:27:47.950 --> 00:27:50.890 align:middle line:84% Base is going to be-- and then I'll plug in a value here. 00:27:50.890 --> 00:27:54.844 align:middle line:84% And the value I want to plug in is this.state.base. 00:27:54.844 --> 00:27:57.890 align:middle line:90% 00:27:57.890 --> 00:28:00.530 align:middle line:84% Again, this code, basically the same as the JavaScript 00:28:00.530 --> 00:28:03.710 align:middle line:84% code that we were using before in order to do the same thing without React. 00:28:03.710 --> 00:28:08.240 align:middle line:84% But I'm making an API request via fetch, requesting data from a server. 00:28:08.240 --> 00:28:12.147 align:middle line:84% I can type in URL here to try and request data from that server. 00:28:12.147 --> 00:28:14.480 align:middle line:84% And right now I'm getting stuff from Exchange Rates API. 00:28:14.480 --> 00:28:16.897 align:middle line:84% But you could imagine getting it from something different. 00:28:16.897 --> 00:28:20.030 align:middle line:84% You could run a Flask web application, for instance, hosted on Heroku 00:28:20.030 --> 00:28:22.890 align:middle line:84% and try and fetch something from that Flask web application. 00:28:22.890 --> 00:28:26.000 align:middle line:84% And so here we can use the React front end to combine 00:28:26.000 --> 00:28:27.350 align:middle line:90% with just about any back end. 00:28:27.350 --> 00:28:29.570 align:middle line:84% Here I'm using the Exchange Rates API back end. 00:28:29.570 --> 00:28:32.360 align:middle line:84% But it could be any Flask web application that you create 00:28:32.360 --> 00:28:35.280 align:middle line:84% or web application server that you create in any other language. 00:28:35.280 --> 00:28:36.410 align:middle line:90% It doesn't really matter. 00:28:36.410 --> 00:28:41.670 align:middle line:84% React will just be able to request information from that back end. 00:28:41.670 --> 00:28:42.750 align:middle line:90% So I fetch it. 00:28:42.750 --> 00:28:44.967 align:middle line:84% And then the syntax here was a little bit strange. 00:28:44.967 --> 00:28:47.050 align:middle line:84% But you might recall that we then said, all right, 00:28:47.050 --> 00:28:51.630 align:middle line:84% then let's take that response and convert it to JSON. 00:28:51.630 --> 00:28:56.727 align:middle line:84% And then with the resulting data, do something with that data. 00:28:56.727 --> 00:28:57.810 align:middle line:90% Was there a question here? 00:28:57.810 --> 00:28:58.357 align:middle line:90% Yeah? 00:28:58.357 --> 00:28:59.610 align:middle line:90% AUDIENCE: [INAUDIBLE] 00:28:59.610 --> 00:29:03.080 align:middle line:84% SPEAKER: Yes, so these here are back ticks around the string. 00:29:03.080 --> 00:29:05.580 align:middle line:84% And the reason I'm using back ticks is that's how JavaScript 00:29:05.580 --> 00:29:10.050 align:middle line:84% does format strings, whereby if I want to insert a value into the string, 00:29:10.050 --> 00:29:13.710 align:middle line:84% like this.state.base, you surround the string with back ticks. 00:29:13.710 --> 00:29:17.790 align:middle line:84% And then you use dollar sign and curly braces to insert a value here. 00:29:17.790 --> 00:29:21.270 align:middle line:84% It's effectively the same as putting the lowercase f in front of a Python string 00:29:21.270 --> 00:29:22.299 align:middle line:90% to insert values there. 00:29:22.299 --> 00:29:25.257 align:middle line:84% Every language just deals with format strings a little bit differently. 00:29:25.257 --> 00:29:29.040 align:middle line:90% 00:29:29.040 --> 00:29:30.580 align:middle line:90% We get back the data. 00:29:30.580 --> 00:29:33.950 align:middle line:84% And if we remember what the API response looks like, 00:29:33.950 --> 00:29:37.470 align:middle line:84% it comes back as a big JSON object that looks something like this. 00:29:37.470 --> 00:29:39.920 align:middle line:90% And it has a key called rates. 00:29:39.920 --> 00:29:43.970 align:middle line:84% And inside of that key called rates is this big object, where 00:29:43.970 --> 00:29:48.650 align:middle line:84% a key is going to be some currency, like New Zealand dollars. 00:29:48.650 --> 00:29:53.420 align:middle line:84% And the value is the exchange rate, 1.47 New Zealand dollars for every 1 US 00:29:53.420 --> 00:29:56.010 align:middle line:90% dollar. 00:29:56.010 --> 00:30:02.520 align:middle line:84% And so once I have this data inside of data.rates and then indexing 00:30:02.520 --> 00:30:08.330 align:middle line:84% into rates this.state.other, that's going to get for me the exchange rate, 00:30:08.330 --> 00:30:10.910 align:middle line:84% because the inside of data, we're going into rates. 00:30:10.910 --> 00:30:14.930 align:middle line:84% And inside of rates, I want whatever the other currency is. 00:30:14.930 --> 00:30:17.820 align:middle line:90% That's the exchange rate that I want. 00:30:17.820 --> 00:30:22.140 align:middle line:84% So I want to go ahead and say this.setState. 00:30:22.140 --> 00:30:25.620 align:middle line:84% Remember that converted was the name of the part of the state that 00:30:25.620 --> 00:30:30.000 align:middle line:84% referred to whatever the value of the converted dollar amount was. 00:30:30.000 --> 00:30:35.910 align:middle line:84% And I'm going to set converted equal to data, get at the rate, 00:30:35.910 --> 00:30:38.053 align:middle line:90% get at the exchange rate. 00:30:38.053 --> 00:30:38.970 align:middle line:90% Is this going to work? 00:30:38.970 --> 00:30:39.512 align:middle line:90% Is this done? 00:30:39.512 --> 00:30:42.460 align:middle line:90% 00:30:42.460 --> 00:30:44.280 align:middle line:90% There's a mathematical bug here. 00:30:44.280 --> 00:30:49.440 align:middle line:90% 00:30:49.440 --> 00:30:49.997 align:middle line:90% Yeah? 00:30:49.997 --> 00:30:53.200 align:middle line:84% AUDIENCE: You need to multiply it by [INAUDIBLE].. 00:30:53.200 --> 00:30:55.810 align:middle line:84% SPEAKER: Yeah, I need to multiply it by a value. 00:30:55.810 --> 00:30:58.480 align:middle line:84% Because if I want to convert $2, then I want 00:30:58.480 --> 00:31:00.430 align:middle line:84% to take whatever the exchange rate is for $1, 00:31:00.430 --> 00:31:03.895 align:middle line:84% and multiply it by 2 to get whatever the converted amount actually is. 00:31:03.895 --> 00:31:06.520 align:middle line:84% So the converted value's just going to be whatever the exchange 00:31:06.520 --> 00:31:10.770 align:middle line:90% rate is multiplied by the value. 00:31:10.770 --> 00:31:15.230 align:middle line:84% So I'm never actually calling this recalculate function anywhere, 00:31:15.230 --> 00:31:17.660 align:middle line:84% although this recalculate function does now hopefully 00:31:17.660 --> 00:31:20.090 align:middle line:84% actually work in terms of getting the exchange rate, 00:31:20.090 --> 00:31:24.170 align:middle line:84% multiplying it by whatever the input value is, and then updating it. 00:31:24.170 --> 00:31:30.440 align:middle line:84% So what I'd like to do is say, any time I change the value in the input field, 00:31:30.440 --> 00:31:32.382 align:middle line:90% let's go ahead and recalculate. 00:31:32.382 --> 00:31:34.090 align:middle line:84% And so you might imagine doing something, 00:31:34.090 --> 00:31:39.820 align:middle line:84% like, OK, this.setState and then this.recalculate, 00:31:39.820 --> 00:31:43.390 align:middle line:84% might be an easy thing to imagine as reasonable logic to do. 00:31:43.390 --> 00:31:47.230 align:middle line:84% Let's update the state, setting the value to event.value.target, and then 00:31:47.230 --> 00:31:49.310 align:middle line:90% do the recalculation. 00:31:49.310 --> 00:31:53.300 align:middle line:84% There's a small problem, though, in terms of the way the JavaScript works. 00:31:53.300 --> 00:31:56.870 align:middle line:84% A lot of JavaScript is asynchronous, meaning 00:31:56.870 --> 00:32:00.890 align:middle line:84% that we might be running this code, this.setState, and then 00:32:00.890 --> 00:32:05.300 align:middle line:84% immediately run this.recalculate, even if the state isn't yet 00:32:05.300 --> 00:32:06.405 align:middle line:90% done being updated. 00:32:06.405 --> 00:32:08.780 align:middle line:84% Like if it happens to be taking the browser a bit of time 00:32:08.780 --> 00:32:12.230 align:middle line:84% to update the state, this.recalculate, in theory, 00:32:12.230 --> 00:32:15.920 align:middle line:90% could be run before this.state is done. 00:32:15.920 --> 00:32:17.990 align:middle line:84% Like, this.state is going to be executed first, 00:32:17.990 --> 00:32:21.590 align:middle line:84% but it could take some time separately and asynchronously. 00:32:21.590 --> 00:32:24.800 align:middle line:84% And we might end up running this.recalculate too early. 00:32:24.800 --> 00:32:27.000 align:middle line:84% And so this is a common enough paradigm in React 00:32:27.000 --> 00:32:29.520 align:middle line:84% that there's some special syntax for doing this. 00:32:29.520 --> 00:32:33.600 align:middle line:84% This.setState can actually take two arguments. 00:32:33.600 --> 00:32:37.550 align:middle line:84% The first argument is the change that you want to make to the state. 00:32:37.550 --> 00:32:40.850 align:middle line:84% But you can also pass to this.setState a function 00:32:40.850 --> 00:32:44.880 align:middle line:84% that you want to run after the state is done updating, not something 00:32:44.880 --> 00:32:46.190 align:middle line:90% that we saw yesterday. 00:32:46.190 --> 00:32:50.150 align:middle line:84% But if I say, all right, let's set state to this new value, 00:32:50.150 --> 00:32:53.370 align:middle line:84% and then give this.setState another argument and say, 00:32:53.370 --> 00:32:59.150 align:middle line:84% all right, this.recalculate, what am effectively saying here 00:32:59.150 --> 00:33:02.990 align:middle line:84% is, yeah, go ahead and set the state, setting 00:33:02.990 --> 00:33:05.760 align:middle line:90% value equal to event.target.value. 00:33:05.760 --> 00:33:08.120 align:middle line:84% But when you're done setting the state, then 00:33:08.120 --> 00:33:10.510 align:middle line:90% run this this.recalculate function. 00:33:10.510 --> 00:33:14.180 align:middle line:84% And that will happen only after the state is done executing. 00:33:14.180 --> 00:33:16.040 align:middle line:84% So it's this optional additional argument 00:33:16.040 --> 00:33:20.900 align:middle line:84% I can give to this.setState to run some calculation after the state has fully 00:33:20.900 --> 00:33:22.283 align:middle line:90% updated. 00:33:22.283 --> 00:33:23.700 align:middle line:90% And so that's what I'd like to do. 00:33:23.700 --> 00:33:26.130 align:middle line:84% When I set the state, I'd like to recalculate 00:33:26.130 --> 00:33:29.160 align:middle line:90% after I've done that update. 00:33:29.160 --> 00:33:32.120 align:middle line:84% So let me go ahead now and refresh the page. 00:33:32.120 --> 00:33:33.470 align:middle line:90% And we'll give this a try. 00:33:33.470 --> 00:33:35.890 align:middle line:90% 0 US dollars equal to 0 euros. 00:33:35.890 --> 00:33:40.350 align:middle line:84% I'll go ahead and delete and type in the number 1. 00:33:40.350 --> 00:33:43.770 align:middle line:84% And we see the number of euros corresponding to 1 US dollar. 00:33:43.770 --> 00:33:46.020 align:middle line:84% I type in the number 2, and I see the number 00:33:46.020 --> 00:33:48.600 align:middle line:90% of euros corresponding to 2 US dollars. 00:33:48.600 --> 00:33:50.270 align:middle line:90% Amazing. 00:33:50.270 --> 00:33:53.090 align:middle line:90% Where's a bug in this application? 00:33:53.090 --> 00:33:54.260 align:middle line:90% Not quite perfect yet. 00:33:54.260 --> 00:33:54.760 align:middle line:90% Yeah? 00:33:54.760 --> 00:33:58.555 align:middle line:90% AUDIENCE: But if you change [INAUDIBLE]. 00:33:58.555 --> 00:33:59.180 align:middle line:90% SPEAKER: Great. 00:33:59.180 --> 00:34:02.347 align:middle line:84% If I change the currency, if I say, OK, I don't want to convert doing euros, 00:34:02.347 --> 00:34:07.640 align:middle line:84% I want to convert between Chinese yuan, for example, and I change it, 00:34:07.640 --> 00:34:11.179 align:middle line:90% nothing about the input field changed. 00:34:11.179 --> 00:34:11.960 align:middle line:90% And why is that? 00:34:11.960 --> 00:34:16.850 align:middle line:84% Well, when I made a selection via this makeSelection function, 00:34:16.850 --> 00:34:21.170 align:middle line:84% I'm updating the state, updating the value of the drop-down. 00:34:21.170 --> 00:34:23.500 align:middle line:90% But I'm not doing the recalculation. 00:34:23.500 --> 00:34:27.590 align:middle line:84% So to fix this, I probably want to also say, after you make a selection, 00:34:27.590 --> 00:34:31.670 align:middle line:84% let's go ahead and also compute this.recalculate in order 00:34:31.670 --> 00:34:35.480 align:middle line:90% to recalculate the correct value. 00:34:35.480 --> 00:34:38.040 align:middle line:90% So I'll go ahead and run this again. 00:34:38.040 --> 00:34:40.440 align:middle line:90% 0 US dollars, 0 euros. 00:34:40.440 --> 00:34:43.380 align:middle line:84% If I say 2 US dollars, I get that number of euros. 00:34:43.380 --> 00:34:47.250 align:middle line:84% If I change it to Japanese yen, then I see, OK, now we 00:34:47.250 --> 00:34:50.527 align:middle line:84% see an update for the number of Japanese yen that corresponded to US dollars. 00:34:50.527 --> 00:34:52.110 align:middle line:90% And it works the other way around too. 00:34:52.110 --> 00:34:54.540 align:middle line:84% I can go here and change this to Canadian dollars, 00:34:54.540 --> 00:34:56.940 align:middle line:84% and it changes to show me how many Japanese yen are 00:34:56.940 --> 00:34:58.770 align:middle line:90% equal to 2 Canadian dollars. 00:34:58.770 --> 00:35:01.330 align:middle line:90% 00:35:01.330 --> 00:35:03.460 align:middle line:84% Questions about any of that and how it worked? 00:35:03.460 --> 00:35:08.240 align:middle line:90% 00:35:08.240 --> 00:35:11.350 align:middle line:84% All right, a couple changes that we could theoretically make here. 00:35:11.350 --> 00:35:14.190 align:middle line:84% One thing is if I have 2 Canadian dollars and I delete it, 00:35:14.190 --> 00:35:16.570 align:middle line:84% like just turn it into the empty string, we 00:35:16.570 --> 00:35:20.540 align:middle line:84% end up with a situation where the number beneath stays the same. 00:35:20.540 --> 00:35:23.770 align:middle line:84% So you could add some logic here in order 00:35:23.770 --> 00:35:30.490 align:middle line:84% to try and handle this particular situation, whereby I could say, 00:35:30.490 --> 00:35:39.810 align:middle line:84% when I change the value of the input field, if ever the converted field-- 00:35:39.810 --> 00:35:43.800 align:middle line:84% I can update the converted field as well, whereby-- 00:35:43.800 --> 00:35:47.950 align:middle line:84% well, actually, I'll backtrack a little bit more. 00:35:47.950 --> 00:35:52.600 align:middle line:84% Right now what's happening is if I make a change, 00:35:52.600 --> 00:35:56.620 align:middle line:84% like change from 2 Canadian dollars to 22 Canadian dollars, 00:35:56.620 --> 00:35:59.560 align:middle line:84% there's going to be some sort of lag here, 00:35:59.560 --> 00:36:02.110 align:middle line:84% whereby I'm making a request to the server 00:36:02.110 --> 00:36:05.260 align:middle line:84% in order to make requests from the Exchange Rates API. 00:36:05.260 --> 00:36:07.960 align:middle line:84% And when I make that request to the Exchange Rates API, 00:36:07.960 --> 00:36:10.190 align:middle line:90% then it's going to update this field. 00:36:10.190 --> 00:36:13.060 align:middle line:84% And so what I might like to do is instead 00:36:13.060 --> 00:36:16.570 align:middle line:84% of just leaving the converted field as is, change it 00:36:16.570 --> 00:36:20.860 align:middle line:84% to something like calculating or some sort of message 00:36:20.860 --> 00:36:24.400 align:middle line:84% to indicate that it is calculating the exchange rate before it actually gives 00:36:24.400 --> 00:36:27.700 align:middle line:84% me back what the exchange rate actually is. 00:36:27.700 --> 00:36:30.250 align:middle line:84% And so to do this, I could do something like this. 00:36:30.250 --> 00:36:33.040 align:middle line:84% When I change the value of the input field, 00:36:33.040 --> 00:36:40.900 align:middle line:84% let me also set the value of converted equal to null, for example, meaning 00:36:40.900 --> 00:36:45.706 align:middle line:84% let me just clear out the value of the converted field, set it equal to null. 00:36:45.706 --> 00:36:48.980 align:middle line:84% And then in this input field, rather than give it 00:36:48.980 --> 00:36:52.160 align:middle line:84% just a value of this.state.converted, let me say 00:36:52.160 --> 00:36:55.880 align:middle line:90% is this.state.converted equal to null? 00:36:55.880 --> 00:37:00.260 align:middle line:84% If it is, then let me just say, calculating. 00:37:00.260 --> 00:37:02.870 align:middle line:84% But otherwise-- and again, this is the ternary operator 00:37:02.870 --> 00:37:04.940 align:middle line:90% that we took a look at yesterday. 00:37:04.940 --> 00:37:08.840 align:middle line:84% Otherwise, then it can be this.state.converted. 00:37:08.840 --> 00:37:11.180 align:middle line:90% So a little bit of extra logic here. 00:37:11.180 --> 00:37:15.110 align:middle line:84% But the logic on line 39 is saying what should show up in that lower input 00:37:15.110 --> 00:37:18.950 align:middle line:84% field if my converted value has null, meaning I haven't given it 00:37:18.950 --> 00:37:20.240 align:middle line:90% an actual number yet? 00:37:20.240 --> 00:37:22.690 align:middle line:84% Then go ahead and display the word calculating. 00:37:22.690 --> 00:37:24.830 align:middle line:84% But if there is an actual number there, then 00:37:24.830 --> 00:37:27.030 align:middle line:90% go ahead and just display that number. 00:37:27.030 --> 00:37:28.840 align:middle line:90% And so now the result is going to be-- 00:37:28.840 --> 00:37:31.370 align:middle line:84% and the API seems to be working rather quickly today. 00:37:31.370 --> 00:37:33.240 align:middle line:84% So maybe we won't be able to notice this. 00:37:33.240 --> 00:37:37.930 align:middle line:84% But if I type 2, and I change it to 21, yeah, there's 00:37:37.930 --> 00:37:39.680 align:middle line:84% a brief moment where you can see that it's 00:37:39.680 --> 00:37:42.980 align:middle line:84% calculating before it actually updates with what the correct answer is. 00:37:42.980 --> 00:37:46.100 align:middle line:84% So there's never a state where I see conflicting information 00:37:46.100 --> 00:37:48.380 align:middle line:84% that the other field just hasn't yet updated. 00:37:48.380 --> 00:37:52.290 align:middle line:84% It will always just say calculating until I've calculated the number. 00:37:52.290 --> 00:37:52.935 align:middle line:90% Yeah? 00:37:52.935 --> 00:37:56.400 align:middle line:90% AUDIENCE: [INAUDIBLE] 00:37:56.400 --> 00:37:57.890 align:middle line:90% 00:37:57.890 --> 00:38:02.750 align:middle line:84% SPEAKER: This.state.converted is part of the state that represents whatever 00:38:02.750 --> 00:38:05.780 align:middle line:90% the value of the converted currency is. 00:38:05.780 --> 00:38:08.930 align:middle line:84% And I have that just because I defined it initially in the state. 00:38:08.930 --> 00:38:09.950 align:middle line:90% I called it converted. 00:38:09.950 --> 00:38:15.510 align:middle line:84% And I'm updating it whenever I want a new value for that input field. 00:38:15.510 --> 00:38:20.130 align:middle line:84% The only small corner case here is that now if I delete and I press Delete 00:38:20.130 --> 00:38:23.610 align:middle line:84% again, go to an empty input field, the other field is just 00:38:23.610 --> 00:38:26.040 align:middle line:84% going to say calculating forever because it's never 00:38:26.040 --> 00:38:27.783 align:middle line:90% going to end up getting a number. 00:38:27.783 --> 00:38:29.700 align:middle line:84% So you could go through and you could fix this 00:38:29.700 --> 00:38:31.530 align:middle line:90% by adding a couple more conditions. 00:38:31.530 --> 00:38:34.140 align:middle line:84% You can see the code in the source code examples 00:38:34.140 --> 00:38:39.360 align:middle line:84% that I posted online that'll help walk you through that as well. 00:38:39.360 --> 00:38:43.670 align:middle line:84% So we now have an application that can do currency conversion 00:38:43.670 --> 00:38:44.907 align:middle line:90% between different currencies. 00:38:44.907 --> 00:38:47.990 align:middle line:84% You can type in different amounts of currency and see the converted value. 00:38:47.990 --> 00:38:50.073 align:middle line:84% You can choose different things from the drop-down 00:38:50.073 --> 00:38:54.260 align:middle line:84% to convert between different currencies but there is some inefficiencies here 00:38:54.260 --> 00:38:54.950 align:middle line:90% still. 00:38:54.950 --> 00:39:04.296 align:middle line:84% Any sense for where the inefficiencies might be or room for improvement? 00:39:04.296 --> 00:39:10.250 align:middle line:90% 00:39:10.250 --> 00:39:15.190 align:middle line:84% So one thing you'd might notice is that any time I change the input field, 00:39:15.190 --> 00:39:18.350 align:middle line:84% or anytime I select a new currency from the drop-down, 00:39:18.350 --> 00:39:20.680 align:middle line:90% we're running the recalculate function. 00:39:20.680 --> 00:39:24.430 align:middle line:84% And the recalculate function is going to parse the number, 00:39:24.430 --> 00:39:28.020 align:middle line:84% reach out to the API via web request, get back some response, 00:39:28.020 --> 00:39:32.020 align:middle line:84% parse that data, and save it inside of the input field. 00:39:32.020 --> 00:39:37.240 align:middle line:84% Which part of this might not be necessary to do every time I type 00:39:37.240 --> 00:39:39.490 align:middle line:90% something into the input field? 00:39:39.490 --> 00:39:39.990 align:middle line:90% Yeah? 00:39:39.990 --> 00:39:41.898 align:middle line:84% AUDIENCE: If you're just changing the number, 00:39:41.898 --> 00:39:44.760 align:middle line:84% but you're keeping the two currencies the same? 00:39:44.760 --> 00:39:47.990 align:middle line:84% SPEAKER: Yeah, if I'm just changing the number, 00:39:47.990 --> 00:39:51.920 align:middle line:84% like if I just change this from 28, press Delete, OK, now 2 US dollars, I'm 00:39:51.920 --> 00:39:55.040 align:middle line:84% making yet another web request to ask the API, like, 00:39:55.040 --> 00:39:58.370 align:middle line:84% what is the exchange rate between US dollars and euros? 00:39:58.370 --> 00:40:01.027 align:middle line:84% And then getting that number, which is almost definitely going 00:40:01.027 --> 00:40:03.110 align:middle line:84% to be the same number that I got like a second ago 00:40:03.110 --> 00:40:05.315 align:middle line:90% when I just did the last calculation. 00:40:05.315 --> 00:40:07.190 align:middle line:84% And I'm reaching out again to get that number 00:40:07.190 --> 00:40:09.190 align:middle line:84% and then doing something with that number, which 00:40:09.190 --> 00:40:11.370 align:middle line:90% is costly in a number of ways. 00:40:11.370 --> 00:40:13.820 align:middle line:84% It's costly on part of the this web application 00:40:13.820 --> 00:40:16.940 align:middle line:84% because I'm reaching out to the server when I probably don't need to. 00:40:16.940 --> 00:40:19.065 align:middle line:84% And it's costly on the part of the API because it's 00:40:19.065 --> 00:40:22.220 align:middle line:84% getting more requests than it needs to handle because there's 00:40:22.220 --> 00:40:24.980 align:middle line:90% some unnecessary requests here. 00:40:24.980 --> 00:40:27.470 align:middle line:84% Now, sure, it's possible that I typed in a number, 00:40:27.470 --> 00:40:30.860 align:middle line:84% and I don't type in another number until, like, tomorrow, by which point 00:40:30.860 --> 00:40:32.960 align:middle line:84% the currency exchange rates might change. 00:40:32.960 --> 00:40:37.490 align:middle line:84% But you might imagine that if I make two requests for the same exchange rate 00:40:37.490 --> 00:40:40.370 align:middle line:84% within, like, a minute of each other, odds 00:40:40.370 --> 00:40:44.300 align:middle line:84% are that it's totally fine to just use the old exchange rate 00:40:44.300 --> 00:40:47.840 align:middle line:84% and not have to recalculate or re-request from the API 00:40:47.840 --> 00:40:50.040 align:middle line:90% what the exchange rate actually is. 00:40:50.040 --> 00:40:52.520 align:middle line:84% And so here we're going to implement what's 00:40:52.520 --> 00:40:56.990 align:middle line:84% called a cache, a way that we can just store information locally rather 00:40:56.990 --> 00:41:00.850 align:middle line:84% than need to reach out to an API in order to access that information. 00:41:00.850 --> 00:41:04.100 align:middle line:84% And what we'd like to say is some sort of model, whereby we can store exchange 00:41:04.100 --> 00:41:06.590 align:middle line:84% rates, and if I try and request the same exchange 00:41:06.590 --> 00:41:10.670 align:middle line:84% rate within a minute of the last time that I requested that exchange rate, 00:41:10.670 --> 00:41:13.190 align:middle line:84% then don't bother making another API request. 00:41:13.190 --> 00:41:16.330 align:middle line:90% Just use the data that we've stored. 00:41:16.330 --> 00:41:17.130 align:middle line:90% Question, yeah? 00:41:17.130 --> 00:41:18.713 align:middle line:90% AUDIENCE: Is there a limit on the API? 00:41:18.713 --> 00:41:23.660 align:middle line:84% Like, if you just [INAUDIBLE] make the request every time [INAUDIBLE].. 00:41:23.660 --> 00:41:27.335 align:middle line:84% Is there a certain point where the API [INAUDIBLE]?? 00:41:27.335 --> 00:41:28.710 align:middle line:90% SPEAKER: It depends upon the API. 00:41:28.710 --> 00:41:31.345 align:middle line:84% Certain APIs impose formal rate limiting, 00:41:31.345 --> 00:41:34.470 align:middle line:84% whereby you can only make a certain number of requests per hour or per day, 00:41:34.470 --> 00:41:35.695 align:middle line:90% for example. 00:41:35.695 --> 00:41:38.820 align:middle line:84% This API happens to not be like that, though they do have a disclaimer that 00:41:38.820 --> 00:41:40.695 align:middle line:84% warns, like, please cache your results, which 00:41:40.695 --> 00:41:45.450 align:middle line:84% is what we're about to do, so as to avoid bogging them down 00:41:45.450 --> 00:41:49.197 align:middle line:84% with many, many requests for constant currency exchange rates. 00:41:49.197 --> 00:41:51.030 align:middle line:84% So it does depend a little bit upon the API. 00:41:51.030 --> 00:41:55.190 align:middle line:90% 00:41:55.190 --> 00:41:57.800 align:middle line:84% Let's try and actually implement this cache. 00:41:57.800 --> 00:42:01.160 align:middle line:84% And you can see this implemented inside of exchange1.html, 00:42:01.160 --> 00:42:04.670 align:middle line:84% if you take a look at the source code examples for today. 00:42:04.670 --> 00:42:08.600 align:middle line:84% So up here at the top, we have this.currencies, 00:42:08.600 --> 00:42:10.550 align:middle line:90% and we also have this.state. 00:42:10.550 --> 00:42:15.140 align:middle line:84% Let me go ahead and add another variable called this.cached, 00:42:15.140 --> 00:42:18.290 align:middle line:84% which is going to store a JavaScript object where 00:42:18.290 --> 00:42:22.730 align:middle line:84% the keys are going to be currency exchange rate bases that I've stored. 00:42:22.730 --> 00:42:25.670 align:middle line:84% And the values are just going to be those currency exchange 00:42:25.670 --> 00:42:31.130 align:middle line:84% rates that I have actually stored inside of my web browser's memory, 00:42:31.130 --> 00:42:33.440 align:middle line:90% in this particular case. 00:42:33.440 --> 00:42:37.520 align:middle line:84% So all the interesting logic is not-- no longer in the interface. 00:42:37.520 --> 00:42:39.470 align:middle line:90% The interface is not changing at all. 00:42:39.470 --> 00:42:42.430 align:middle line:84% The only thing that's changing is my recalculate function. 00:42:42.430 --> 00:42:45.960 align:middle line:90% How am I doing this recalculation? 00:42:45.960 --> 00:42:50.040 align:middle line:84% Well, let me say, when I get this data back, before I set the state, 00:42:50.040 --> 00:42:52.090 align:middle line:90% let's update this.cached. 00:42:52.090 --> 00:42:55.890 align:middle line:84% Let's update what's inside of the cache, in particular 00:42:55.890 --> 00:43:03.340 align:middle line:84% at the key this.state.base, meaning update inside the cache. 00:43:03.340 --> 00:43:06.490 align:middle line:84% I need a different value in the cache for every different base currency, 00:43:06.490 --> 00:43:09.670 align:middle line:84% because I want to be able to store different possible base currencies. 00:43:09.670 --> 00:43:11.440 align:middle line:90% And I'm going to store two things. 00:43:11.440 --> 00:43:16.240 align:middle line:84% I'm going to store the exchange rates, which is going to be in data.rates. 00:43:16.240 --> 00:43:18.750 align:middle line:84% And again, this is just a JavaScript object. 00:43:18.750 --> 00:43:24.100 align:middle line:84% And I'm also going to store a timestamp, meaning at what time did I 00:43:24.100 --> 00:43:26.200 align:middle line:90% insert this data into the cache? 00:43:26.200 --> 00:43:28.360 align:middle line:84% At what time that I make the initial request? 00:43:28.360 --> 00:43:30.085 align:middle line:90% And save that data. 00:43:30.085 --> 00:43:31.960 align:middle line:84% And in JavaScript, there's a special function 00:43:31.960 --> 00:43:35.890 align:middle line:84% called date.now, which will just get us a date object that 00:43:35.890 --> 00:43:38.650 align:middle line:90% represent the current timestamp. 00:43:38.650 --> 00:43:39.800 align:middle line:90% So what's happening here? 00:43:39.800 --> 00:43:43.300 align:middle line:84% I'm making a request to the API, taking the resulting data, 00:43:43.300 --> 00:43:47.500 align:middle line:84% and storing it inside of the cache, saving it inside of some variable, 00:43:47.500 --> 00:43:50.890 align:middle line:84% whereby that variable is going to store the exchange rates, 00:43:50.890 --> 00:43:57.277 align:middle line:84% and it's also going to store the current timestamp, the timestamp for right now. 00:43:57.277 --> 00:43:59.110 align:middle line:84% And then we're going to go through with what 00:43:59.110 --> 00:44:02.530 align:middle line:84% we did before of setting the state, updating it 00:44:02.530 --> 00:44:05.290 align:middle line:84% to whatever they exchange rate is times the dollar amount 00:44:05.290 --> 00:44:07.950 align:middle line:90% that we're trying to convert. 00:44:07.950 --> 00:44:10.500 align:middle line:84% But now that we have this cache, we can add some logic 00:44:10.500 --> 00:44:13.710 align:middle line:84% before we make this API request so that we don't 00:44:13.710 --> 00:44:16.650 align:middle line:90% need to always make this API request. 00:44:16.650 --> 00:44:19.740 align:middle line:84% In particular, we can add an if statement. 00:44:19.740 --> 00:44:22.680 align:middle line:84% I want to check to see whether or not-- well, I 00:44:22.680 --> 00:44:24.130 align:middle line:90% want to check to see two things. 00:44:24.130 --> 00:44:28.290 align:middle line:84% One, is this base currency already in the cache? 00:44:28.290 --> 00:44:31.110 align:middle line:84% In which case, I don't need to make another API request. 00:44:31.110 --> 00:44:34.770 align:middle line:84% And if it is already in the cache, has it been less than, 00:44:34.770 --> 00:44:39.340 align:middle line:84% say, a minute since the last time that I made this request? 00:44:39.340 --> 00:44:42.358 align:middle line:84% So this is the idea of what's called cache invalidation, the idea 00:44:42.358 --> 00:44:44.650 align:middle line:84% that after a certain point in time, this cache is going 00:44:44.650 --> 00:44:47.880 align:middle line:84% to be considered stale or invalid, and I want to go ahead and make the API 00:44:47.880 --> 00:44:48.570 align:middle line:90% request anyway. 00:44:48.570 --> 00:44:50.862 align:middle line:84% If I make the-- if I check again tomorrow, 00:44:50.862 --> 00:44:53.070 align:middle line:84% the exchange rates are probably change, so I probably 00:44:53.070 --> 00:44:55.115 align:middle line:84% want to get the most up-to-date exchange rate. 00:44:55.115 --> 00:44:57.240 align:middle line:84% But within a certain period of time, like a minute, 00:44:57.240 --> 00:44:59.735 align:middle line:90% it's probably not going to change much. 00:44:59.735 --> 00:45:01.110 align:middle line:90% And so how am I going to do this? 00:45:01.110 --> 00:45:09.080 align:middle line:84% Well, if it is in the cache, it'll be in this.cached, this.state.base, right? 00:45:09.080 --> 00:45:11.420 align:middle line:90% This variable is the same as this. 00:45:11.420 --> 00:45:13.430 align:middle line:84% This is where I'm storing the information 00:45:13.430 --> 00:45:15.530 align:middle line:90% if it is, in fact, inside the cache. 00:45:15.530 --> 00:45:23.240 align:middle line:84% And let me first check to make sure it's not equal to undefined. 00:45:23.240 --> 00:45:26.990 align:middle line:84% If I try and index into a JavaScript object into a key that doesn't exist, 00:45:26.990 --> 00:45:30.140 align:middle line:84% the value I get back is a special value called undefined. 00:45:30.140 --> 00:45:32.240 align:middle line:84% And so if it's not equal to undefined, that 00:45:32.240 --> 00:45:35.060 align:middle line:84% means there's actually something in the cache. 00:45:35.060 --> 00:45:41.090 align:middle line:84% But I also want to make sure that it's been at most a minute 00:45:41.090 --> 00:45:44.280 align:middle line:84% since the last time that I updated the cache. 00:45:44.280 --> 00:45:46.400 align:middle line:90% And so how am I going to do that. 00:45:46.400 --> 00:45:50.930 align:middle line:84% Well, let's take the current timestamp, date.now, 00:45:50.930 --> 00:45:55.810 align:middle line:84% and let's subtract the timestamp in the cache, 00:45:55.810 --> 00:46:00.940 align:middle line:84% so the current timestamp minus this.cached, this.state.base-- 00:46:00.940 --> 00:46:02.230 align:middle line:90% that's what's in the cache-- 00:46:02.230 --> 00:46:07.860 align:middle line:84% dot timestamp to say get at the timestamp key 00:46:07.860 --> 00:46:10.680 align:middle line:90% of whatever is in the cache. 00:46:10.680 --> 00:46:15.600 align:middle line:84% And so I'm taking the current date, subtracting the time at which point 00:46:15.600 --> 00:46:18.470 align:middle line:90% I put the data in the cache. 00:46:18.470 --> 00:46:22.958 align:middle line:84% And as long as that is less than a minute, 00:46:22.958 --> 00:46:25.750 align:middle line:84% this subtraction is going to return to me a number in milliseconds. 00:46:25.750 --> 00:46:31.280 align:middle line:84% So a minute is going to be 1,000 milliseconds times 60 seconds. 00:46:31.280 --> 00:46:33.350 align:middle line:84% So long as the difference between now and when 00:46:33.350 --> 00:46:38.210 align:middle line:84% the time I put things in the cache is less than 1 minute, then let's go ahead 00:46:38.210 --> 00:46:42.880 align:middle line:90% and draw the information from the cache. 00:46:42.880 --> 00:46:50.650 align:middle line:84% And so to do that, we'll go ahead and say, this.setState, 00:46:50.650 --> 00:46:53.350 align:middle line:90% setting the converted value. 00:46:53.350 --> 00:46:59.640 align:middle line:84% Originally, the converted value was equal to this value, data.rates, 00:46:59.640 --> 00:47:02.760 align:middle line:90% this.state.other times value. 00:47:02.760 --> 00:47:05.910 align:middle line:84% But it's no longer going to be stored in data.rates. 00:47:05.910 --> 00:47:13.650 align:middle line:84% Instead of data, the information is stored in the cache, so this.cached, 00:47:13.650 --> 00:47:18.980 align:middle line:84% this.state.base, get at the exchange rates in the cache, 00:47:18.980 --> 00:47:24.100 align:middle line:84% convert it to the other currency, and multiply it by the value. 00:47:24.100 --> 00:47:26.140 align:middle line:90% So fair amount of code here. 00:47:26.140 --> 00:47:28.720 align:middle line:84% We'll zoom out, see if you can see what's going on here. 00:47:28.720 --> 00:47:29.720 align:middle line:90% We have a condition. 00:47:29.720 --> 00:47:31.390 align:middle line:90% It's running a check. 00:47:31.390 --> 00:47:34.630 align:middle line:84% The first part of the check is saying, is there actually 00:47:34.630 --> 00:47:37.240 align:middle line:84% something in the cache for this currency? 00:47:37.240 --> 00:47:40.720 align:middle line:84% Take the cache, look up the base currency. 00:47:40.720 --> 00:47:43.990 align:middle line:84% If it's undefined, there's nothing in the cache, so we can't do anything. 00:47:43.990 --> 00:47:47.210 align:middle line:84% So we're checking to make sure there's actually something there. 00:47:47.210 --> 00:47:50.690 align:middle line:84% And if there is something there, let's make sure it's recent enough to use. 00:47:50.690 --> 00:47:54.010 align:middle line:84% Let's take the current timestamp, subtract the time 00:47:54.010 --> 00:47:56.470 align:middle line:84% that we put the data in the cache, and make 00:47:56.470 --> 00:48:02.980 align:middle line:84% sure it's less than 1 minute, 1,000 milliseconds times 60 seconds. 00:48:02.980 --> 00:48:05.360 align:middle line:84% Assuming this cache is valid and we can use it, 00:48:05.360 --> 00:48:10.660 align:middle line:84% we'll set the state, updating the value of the converted input field 00:48:10.660 --> 00:48:15.160 align:middle line:84% and say, all right, let's take the value of the cache for this base currency, 00:48:15.160 --> 00:48:18.220 align:middle line:84% get the exchange rate for the other currency, 00:48:18.220 --> 00:48:22.517 align:middle line:84% and multiply it by whatever value was typed in. 00:48:22.517 --> 00:48:24.850 align:middle line:84% At that point, we don't need to go on with the function, 00:48:24.850 --> 00:48:27.340 align:middle line:84% we've already been able to update the state. 00:48:27.340 --> 00:48:32.821 align:middle line:84% So I can just hit Return and say exit the function now. 00:48:32.821 --> 00:48:34.187 align:middle line:90% A lot of code going on there. 00:48:34.187 --> 00:48:36.020 align:middle line:84% I encourage you to take a closer look at it. 00:48:36.020 --> 00:48:37.910 align:middle line:90% It's on the course website. 00:48:37.910 --> 00:48:41.090 align:middle line:84% And if I open up exchange.html now, the first time I 00:48:41.090 --> 00:48:45.350 align:middle line:84% type in currency, like 1 US dollar, it's going to calculate for a moment. 00:48:45.350 --> 00:48:48.193 align:middle line:84% But now if I update it, say, 12 US dollars, 00:48:48.193 --> 00:48:49.610 align:middle line:90% the update's almost instantaneous. 00:48:49.610 --> 00:48:51.527 align:middle line:84% You don't see calculating and then it changes, 00:48:51.527 --> 00:48:53.630 align:middle line:84% because there's no longer this additional couple 00:48:53.630 --> 00:48:57.770 align:middle line:84% milliseconds of latency of going to the server, requesting the exchange rates, 00:48:57.770 --> 00:48:59.400 align:middle line:90% and then using that information. 00:48:59.400 --> 00:49:01.100 align:middle line:90% It's just going to be using the cache. 00:49:01.100 --> 00:49:03.725 align:middle line:84% It's going to compare to whatever current value is in the cache 00:49:03.725 --> 00:49:05.370 align:middle line:90% to say this is within a minute. 00:49:05.370 --> 00:49:07.610 align:middle line:84% Let me just go ahead and update myself to go ahead 00:49:07.610 --> 00:49:12.540 align:middle line:84% and use the value that's stored inside of the cache. 00:49:12.540 --> 00:49:16.950 align:middle line:84% Questions about that idea of why we did it, of how we did it? 00:49:16.950 --> 00:49:23.060 align:middle line:90% 00:49:23.060 --> 00:49:23.560 align:middle line:90% Yeah? 00:49:23.560 --> 00:49:28.480 align:middle line:84% AUDIENCE: Yeah, so just in terms of the syntax, I'm a little bit confused. 00:49:28.480 --> 00:49:33.400 align:middle line:84% When you have this.cached bracket this.state.base, bracket dot rates, 00:49:33.400 --> 00:49:37.010 align:middle line:84% when do you use period, and when do you use brackets when you're [INAUDIBLE]?? 00:49:37.010 --> 00:49:38.010 align:middle line:90% SPEAKER: Great question. 00:49:38.010 --> 00:49:40.802 align:middle line:84% When do you use periods when you're going into a JavaScript object? 00:49:40.802 --> 00:49:42.290 align:middle line:90% When do you use the brackets? 00:49:42.290 --> 00:49:44.930 align:middle line:84% Long story short, they're basically interchangeable, 00:49:44.930 --> 00:49:49.310 align:middle line:84% whereby if I go into the console here, and I have a JavaScript object-- 00:49:49.310 --> 00:49:50.900 align:middle line:90% I'll call it const object-- 00:49:50.900 --> 00:49:56.660 align:middle line:84% that has a key of A and a value of 2 and a key of B and a value of 8, 00:49:56.660 --> 00:50:02.030 align:middle line:84% for example, I can say object.a to get at the A property of the object. 00:50:02.030 --> 00:50:05.930 align:middle line:84% Or I could also say, object square bracket and then in quotation marks 00:50:05.930 --> 00:50:08.750 align:middle line:84% "B" to get at the B property of the object. 00:50:08.750 --> 00:50:10.310 align:middle line:90% And those will work the same way. 00:50:10.310 --> 00:50:14.300 align:middle line:84% Generally speaking, if there is a fixed name of a property of the object 00:50:14.300 --> 00:50:16.650 align:middle line:84% that I want, like I know it's A, for example, 00:50:16.650 --> 00:50:20.510 align:middle line:84% I'll just use the dot notation, object.a, to get at the A property. 00:50:20.510 --> 00:50:24.560 align:middle line:84% But sometimes my program doesn't know in advance what the property is. 00:50:24.560 --> 00:50:29.470 align:middle line:84% Like, I have some variable called key, which is set to B, for example. 00:50:29.470 --> 00:50:34.100 align:middle line:84% And if I want to access the key property, I can't say object.key. 00:50:34.100 --> 00:50:36.060 align:middle line:90% That's undefined. 00:50:36.060 --> 00:50:38.060 align:middle line:84% That's looking for something inside of my object 00:50:38.060 --> 00:50:40.250 align:middle line:90% with a key that's literally called key. 00:50:40.250 --> 00:50:43.520 align:middle line:84% If key is a variable and I want to look it up inside the object, 00:50:43.520 --> 00:50:47.490 align:middle line:84% I'll need to do object square bracket key to say, 00:50:47.490 --> 00:50:50.150 align:middle line:84% all right, let's get at the key property of the object. 00:50:50.150 --> 00:50:52.700 align:middle line:84% So you could just use square brackets for everything. 00:50:52.700 --> 00:50:55.617 align:middle line:84% But the dot notation sometimes just makes things a little bit cleaner. 00:50:55.617 --> 00:50:56.690 align:middle line:90% And so I'll use that too. 00:50:56.690 --> 00:50:58.940 align:middle line:84% But, yeah, good question and good clarification there. 00:50:58.940 --> 00:51:02.510 align:middle line:90% 00:51:02.510 --> 00:51:03.100 align:middle line:90% Other things? 00:51:03.100 --> 00:51:07.050 align:middle line:90% 00:51:07.050 --> 00:51:07.550 align:middle line:90% Yeah? 00:51:07.550 --> 00:51:13.102 align:middle line:84% AUDIENCE: Do you [INAUDIBLE] differences between cache and local storage? 00:51:13.102 --> 00:51:14.310 align:middle line:90% SPEAKER: Yeah, good question. 00:51:14.310 --> 00:51:17.143 align:middle line:84% So cache, local storage, cookies, what is the difference between all 00:51:17.143 --> 00:51:17.730 align:middle line:90% these things? 00:51:17.730 --> 00:51:20.390 align:middle line:84% So a cache can come in a number of different forms. 00:51:20.390 --> 00:51:23.207 align:middle line:84% Your computer, CPU, has a cache that it uses 00:51:23.207 --> 00:51:25.290 align:middle line:84% when it's reading things from memory, for example, 00:51:25.290 --> 00:51:27.915 align:middle line:84% that is lower level than what we're dealing with in this class. 00:51:27.915 --> 00:51:30.290 align:middle line:84% A cache you can think of as just a general term 00:51:30.290 --> 00:51:35.570 align:middle line:84% for any way of storing data in a place that's easier to access, for instance. 00:51:35.570 --> 00:51:39.980 align:middle line:84% So you might-- your web browser, for example, probably has 00:51:39.980 --> 00:51:43.083 align:middle line:84% a cache for web pages, whereby when it's loading a web page, 00:51:43.083 --> 00:51:45.500 align:middle line:84% it could just reload the web page that it has in the cache 00:51:45.500 --> 00:51:48.350 align:middle line:84% rather than try and request the whole web page again. 00:51:48.350 --> 00:51:52.630 align:middle line:84% And so caches come in many different forms, and it's a very general term. 00:51:52.630 --> 00:51:54.380 align:middle line:84% The type of cache we're using here is just 00:51:54.380 --> 00:51:58.070 align:middle line:84% the cache that's being stored inside of our browser's memory that's 00:51:58.070 --> 00:51:59.810 align:middle line:90% going to store the exchange rates. 00:51:59.810 --> 00:52:02.090 align:middle line:84% But if I were to close this page and reopen it, 00:52:02.090 --> 00:52:06.350 align:middle line:84% that cache would be wiped clean because I reset the value of the cache. 00:52:06.350 --> 00:52:14.420 align:middle line:84% Every time I construct a brand-new example of an app, in this case, 00:52:14.420 --> 00:52:16.130 align:middle line:90% in this exchange rate program. 00:52:16.130 --> 00:52:19.610 align:middle line:84% Local storage, meanwhile, you can think of as a type of cache 00:52:19.610 --> 00:52:22.970 align:middle line:84% whose job it is, is to store information inside the browser, 00:52:22.970 --> 00:52:27.740 align:middle line:84% in particular so that information can be used by my application 00:52:27.740 --> 00:52:30.140 align:middle line:84% later if I open it up at a different time. 00:52:30.140 --> 00:52:32.990 align:middle line:84% It's especially useful for being able to store information 00:52:32.990 --> 00:52:36.980 align:middle line:84% inside the browser that will persist even when I close the page 00:52:36.980 --> 00:52:37.700 align:middle line:90% and reopen it. 00:52:37.700 --> 00:52:39.908 align:middle line:84% Because otherwise that probably wouldn't be the case. 00:52:39.908 --> 00:52:43.100 align:middle line:84% And that's all happening on the client side, on the front end. 00:52:43.100 --> 00:52:45.530 align:middle line:84% Cookies, meanwhile, you can think of as having 00:52:45.530 --> 00:52:49.730 align:middle line:84% to do with the interaction between the server and the user, 00:52:49.730 --> 00:52:52.790 align:middle line:84% the client, whereby if you have a cookie, 00:52:52.790 --> 00:52:57.200 align:middle line:84% you can think of it as a way of the server keeping track of who you are, 00:52:57.200 --> 00:53:01.520 align:middle line:84% such that if the user, the client, is sending a cookie along with every web 00:53:01.520 --> 00:53:04.940 align:middle line:84% request it makes to the server, if the server sees that cookie multiple times, 00:53:04.940 --> 00:53:09.200 align:middle line:84% it knows, OK, I know who this individual is based upon the value of the cookie, 00:53:09.200 --> 00:53:11.953 align:middle line:90% for example. 00:53:11.953 --> 00:53:14.120 align:middle line:84% There are also ways for cookies to store information 00:53:14.120 --> 00:53:18.080 align:middle line:84% about the state of the current user's interaction with a server, 00:53:18.080 --> 00:53:23.070 align:middle line:84% though we haven't really touched on that in this class. 00:53:23.070 --> 00:53:23.630 align:middle line:90% Yeah? 00:53:23.630 --> 00:53:24.963 align:middle line:90% AUDIENCE: Just a quick question. 00:53:24.963 --> 00:53:29.130 align:middle line:84% Why would this.currencies in this.cached have their own separate variables 00:53:29.130 --> 00:53:33.210 align:middle line:84% rather than including them in this.state? 00:53:33.210 --> 00:53:34.450 align:middle line:90% SPEAKER: Good question. 00:53:34.450 --> 00:53:37.260 align:middle line:84% So why is it that this.currencies, this.cached are separate? 00:53:37.260 --> 00:53:40.080 align:middle line:84% Currencies is a separate because it's not really 00:53:40.080 --> 00:53:43.980 align:middle line:84% something about the application that is going to change, 00:53:43.980 --> 00:53:47.928 align:middle line:84% insofar as it's basically just a fixed list of variables. 00:53:47.928 --> 00:53:50.220 align:middle line:84% I could have effectively pulled this out of it entirely 00:53:50.220 --> 00:53:53.640 align:middle line:84% and just made it a constant variable inside my JavaScript, like said, 00:53:53.640 --> 00:53:58.300 align:middle line:84% const currency equals something, for instance. 00:53:58.300 --> 00:54:02.770 align:middle line:84% And the cache is sort of separate because nothing 00:54:02.770 --> 00:54:08.140 align:middle line:84% about what the application looks like is really dependent upon the cache. 00:54:08.140 --> 00:54:12.340 align:middle line:84% It's only dependent upon the values of base, other value, and converted. 00:54:12.340 --> 00:54:16.240 align:middle line:84% And our recalculate function uses the cache to give converted a value. 00:54:16.240 --> 00:54:19.810 align:middle line:84% But the interface itself is only based upon the value of the converted thing. 00:54:19.810 --> 00:54:29.690 align:middle line:90% 00:54:29.690 --> 00:54:34.880 align:middle line:84% So a couple of things I'll talk about briefly, the first of which 00:54:34.880 --> 00:54:37.910 align:middle line:84% is going to be options that you'll have for the morning project. 00:54:37.910 --> 00:54:39.618 align:middle line:84% I'll talk about the morning project first 00:54:39.618 --> 00:54:41.930 align:middle line:90% before I dive into one last example. 00:54:41.930 --> 00:54:44.150 align:middle line:84% And because we are reaching-- well, actually, sorry. 00:54:44.150 --> 00:54:47.150 align:middle line:84% Before I talk about the morning project, one thing that I should mention 00:54:47.150 --> 00:54:50.090 align:middle line:84% is how React is typically used in practice, whereby 00:54:50.090 --> 00:54:51.950 align:middle line:84% so far, when we've been writing React code, 00:54:51.950 --> 00:54:56.000 align:middle line:84% we've been writing this React code purely inside of this HTML page, where 00:54:56.000 --> 00:54:59.570 align:middle line:84% we've been including in the JavaScript section some JSX code, 00:54:59.570 --> 00:55:02.090 align:middle line:84% JSX code being the version of JavaScript that 00:55:02.090 --> 00:55:05.960 align:middle line:84% allows me to have HTML elements embedded inside the JavaScript. 00:55:05.960 --> 00:55:09.110 align:middle line:84% This is not normal JavaScript code and not code 00:55:09.110 --> 00:55:12.410 align:middle line:84% that our browsers natively are able to understand. 00:55:12.410 --> 00:55:15.078 align:middle line:84% And this is why we've been including this Babel package up here 00:55:15.078 --> 00:55:17.120 align:middle line:84% in the header section of our page, which is going 00:55:17.120 --> 00:55:20.900 align:middle line:84% to take care of the job of transpiling our code from JSX 00:55:20.900 --> 00:55:24.080 align:middle line:84% into plain-old JavaScript so that our browser can understand it. 00:55:24.080 --> 00:55:27.350 align:middle line:84% In practice, this is not the type of program that you would want to deploy, 00:55:27.350 --> 00:55:28.790 align:middle line:90% at least not in this form. 00:55:28.790 --> 00:55:33.260 align:middle line:84% And in fact, when you open up any of the problems we've been doing so far, 00:55:33.260 --> 00:55:37.280 align:middle line:84% you'll see this warning that says, you are using the in-browser Babel 00:55:37.280 --> 00:55:38.180 align:middle line:90% transformer. 00:55:38.180 --> 00:55:40.940 align:middle line:84% Be sure to pre-compile your scripts for production. 00:55:40.940 --> 00:55:42.800 align:middle line:84% And what that warning is basically saying 00:55:42.800 --> 00:55:48.110 align:middle line:84% is rather than deploy something that is JSX code plus the Babel 00:55:48.110 --> 00:55:50.360 align:middle line:84% transformer, that's basically translating code 00:55:50.360 --> 00:55:53.900 align:middle line:84% from one language to another, and have that translation process happen 00:55:53.900 --> 00:55:57.350 align:middle line:84% every single time someone opens a page on your web page, 00:55:57.350 --> 00:56:01.010 align:middle line:84% we can just pre-compile all of those scripts once. 00:56:01.010 --> 00:56:03.380 align:middle line:84% Before we release our application for production, 00:56:03.380 --> 00:56:06.170 align:middle line:84% we can say, go ahead and take all of that JSX code, 00:56:06.170 --> 00:56:09.600 align:middle line:84% compile it into plain-old JavaScript code, and let's just deploy 00:56:09.600 --> 00:56:10.820 align:middle line:90% the JavaScript code. 00:56:10.820 --> 00:56:12.410 align:middle line:90% That way we compile it once. 00:56:12.410 --> 00:56:15.770 align:middle line:84% And then anyone who uses our page can just open the page normally, 00:56:15.770 --> 00:56:19.940 align:middle line:84% no translation necessary because it's already in plain-old JavaScript. 00:56:19.940 --> 00:56:22.520 align:middle line:84% And so there are a number of tools for being able to do this. 00:56:22.520 --> 00:56:24.710 align:middle line:84% But perhaps the most common and most popular 00:56:24.710 --> 00:56:30.080 align:middle line:84% is a special program created by Facebook called Create React App. 00:56:30.080 --> 00:56:32.450 align:middle line:84% In order to use Create React App, you'll need 00:56:32.450 --> 00:56:36.900 align:middle line:84% to install something called Node or Node.js on your computer. 00:56:36.900 --> 00:56:39.920 align:middle line:84% Node.js is just what's called at JavaScript runtime. 00:56:39.920 --> 00:56:42.980 align:middle line:84% You can think of it as a way of getting JavaScript code 00:56:42.980 --> 00:56:44.720 align:middle line:90% to run just about anywhere. 00:56:44.720 --> 00:56:47.510 align:middle line:84% You can use JavaScript on the server, in addition 00:56:47.510 --> 00:56:49.590 align:middle line:90% to using it just on the client. 00:56:49.590 --> 00:56:52.100 align:middle line:84% But if you install Node.js on your computer, 00:56:52.100 --> 00:56:57.260 align:middle line:84% you can then get access to a program called NPM, the Node Package Manager. 00:56:57.260 --> 00:56:59.270 align:middle line:84% And there's a particular package called Create 00:56:59.270 --> 00:57:03.110 align:middle line:84% React App, which is going to build for you a React app that 00:57:03.110 --> 00:57:07.610 align:middle line:84% has a lot of scripts, useful scripts and tools that are already built into it. 00:57:07.610 --> 00:57:10.938 align:middle line:84% And so you're not going to need this for the purposes of this class. 00:57:10.938 --> 00:57:12.230 align:middle line:90% But I wanted to show it to you. 00:57:12.230 --> 00:57:14.188 align:middle line:84% Because if you ever go into production in order 00:57:14.188 --> 00:57:16.400 align:middle line:84% to build applications with React, you're probably 00:57:16.400 --> 00:57:19.648 align:middle line:84% not going to be just putting it in the script section of your HTML page. 00:57:19.648 --> 00:57:21.440 align:middle line:84% You're probably going to be doing something 00:57:21.440 --> 00:57:23.100 align:middle line:90% a little more along these lines. 00:57:23.100 --> 00:57:27.320 align:middle line:84% So once you install Create React App, you 00:57:27.320 --> 00:57:32.720 align:middle line:84% can create a new React application by just typing create-react-app, 00:57:32.720 --> 00:57:34.860 align:middle line:90% followed by the name of the application. 00:57:34.860 --> 00:57:37.532 align:middle line:84% So I want to create an application called Hello. 00:57:37.532 --> 00:57:40.490 align:middle line:84% And again, you're going to need to install Node and then install Create 00:57:40.490 --> 00:57:42.480 align:middle line:90% React App in order for this to work. 00:57:42.480 --> 00:57:45.500 align:middle line:90% But I type create-react-app Hello. 00:57:45.500 --> 00:57:47.180 align:middle line:90% It's just the name of an application. 00:57:47.180 --> 00:57:49.770 align:middle line:84% And then the Node package manager is going 00:57:49.770 --> 00:57:53.360 align:middle line:84% to go through a long step of fetching all these packages and useful scripts 00:57:53.360 --> 00:57:54.620 align:middle line:90% that it's going to use for me. 00:57:54.620 --> 00:58:00.890 align:middle line:84% And it's going to build for me the basis of an application written in React. 00:58:00.890 --> 00:58:04.460 align:middle line:84% And it's going to give me a starter application, basically, a foundation 00:58:04.460 --> 00:58:06.410 align:middle line:90% on which I can start to build. 00:58:06.410 --> 00:58:09.930 align:middle line:84% Once it's done, I'm going to CD into the Hello directory. 00:58:09.930 --> 00:58:11.930 align:middle line:84% And if I type that last and look what's in here, 00:58:11.930 --> 00:58:14.055 align:middle line:84% there's all sorts of stuff that's actually in here. 00:58:14.055 --> 00:58:17.250 align:middle line:84% I have public, which is going to store a bunch of files 00:58:17.250 --> 00:58:19.670 align:middle line:84% that our web application might use, a source folder, 00:58:19.670 --> 00:58:22.340 align:middle line:84% where all the JavaScript code is actually going to be located, 00:58:22.340 --> 00:58:26.203 align:middle line:84% Node modules, which is a special folder for including other packages, 00:58:26.203 --> 00:58:28.370 align:middle line:84% much in the same way that in Flask we would import-- 00:58:28.370 --> 00:58:31.130 align:middle line:84% in Python, we would import other modules that we might use. 00:58:31.130 --> 00:58:33.530 align:middle line:84% In Node, you can also have modules that you install 00:58:33.530 --> 00:58:36.400 align:middle line:90% to give you additional capabilities. 00:58:36.400 --> 00:58:39.870 align:middle line:84% But once you're in here, the way to run this React application 00:58:39.870 --> 00:58:46.345 align:middle line:84% is just to say NPM run start to actually start running this application. 00:58:46.345 --> 00:58:49.470 align:middle line:84% And what that's going to do is it's going to start up this web application, 00:58:49.470 --> 00:58:53.130 align:middle line:84% and it's going to give me a default React application that's just going 00:58:53.130 --> 00:58:55.360 align:middle line:90% to display, I think, the React logo. 00:58:55.360 --> 00:58:55.860 align:middle line:90% Yeah. 00:58:55.860 --> 00:58:58.710 align:middle line:84% So this is the default React application that React gives you 00:58:58.710 --> 00:59:01.350 align:middle line:90% if use Create React App. 00:59:01.350 --> 00:59:03.845 align:middle line:84% But the nice thing about this is that it automatically 00:59:03.845 --> 00:59:06.840 align:middle line:90% has separated things into files for me. 00:59:06.840 --> 00:59:15.080 align:middle line:84% So that if I go into Hello and go into Source, 00:59:15.080 --> 00:59:19.490 align:middle line:84% my source folder has an app.js file, where 00:59:19.490 --> 00:59:23.180 align:middle line:84% they're defining an app component that, again, has a render function that 00:59:23.180 --> 00:59:28.080 align:middle line:90% says editApp.js and save to reload. 00:59:28.080 --> 00:59:30.620 align:middle line:84% And so this is already getting into the structure 00:59:30.620 --> 00:59:32.510 align:middle line:84% of what most React applications look like, 00:59:32.510 --> 00:59:34.880 align:middle line:84% which is rather than having all of the components 00:59:34.880 --> 00:59:40.580 align:middle line:84% inside of the same HTML page, have a different app.js file for the app 00:59:40.580 --> 00:59:44.390 align:middle line:84% component and have something else dot JS file for some other component 00:59:44.390 --> 00:59:47.120 align:middle line:84% and just separate all of your components into different files. 00:59:47.120 --> 00:59:49.850 align:middle line:84% It separates the CSS into different files as well 00:59:49.850 --> 00:59:52.640 align:middle line:84% and just starts the process of trying to separate things out. 00:59:52.640 --> 00:59:55.778 align:middle line:84% If you use Create React App, it also has dynamic reloading, 00:59:55.778 --> 00:59:57.320 align:middle line:90% the way that your Flask app might do. 00:59:57.320 --> 00:59:59.180 align:middle line:84% But you don't even need to refresh the page. 00:59:59.180 --> 01:00:05.240 align:middle line:84% Instead of editSource.app.js and save to reload, I can replace this with Welcome 01:00:05.240 --> 01:00:08.160 align:middle line:90% to CS50 Beyond and save that. 01:00:08.160 --> 01:00:10.540 align:middle line:84% And without doing anything, if I just go back to Chrome, 01:00:10.540 --> 01:00:13.610 align:middle line:84% my page is already updated with whatever it is that I changed. 01:00:13.610 --> 01:00:15.800 align:middle line:84% So every time you save, Create React App will 01:00:15.800 --> 01:00:17.930 align:middle line:84% take care of the process of auto reloading or hot 01:00:17.930 --> 01:00:21.470 align:middle line:84% reloading the web page up in order to reflect whatever I've changed, so very 01:00:21.470 --> 01:00:24.810 align:middle line:84% useful for development, such that you can just make a change, save it, 01:00:24.810 --> 01:00:29.100 align:middle line:84% and the page will automatically reload to reflect those changes. 01:00:29.100 --> 01:00:31.150 align:middle line:90% So this is very helpful for development. 01:00:31.150 --> 01:00:34.500 align:middle line:84% But when I'm ready to actually build this program in order 01:00:34.500 --> 01:00:36.900 align:middle line:84% to ship it, for example, I would run something 01:00:36.900 --> 01:00:41.840 align:middle line:84% like NPM run build inside of my Hello directory. 01:00:41.840 --> 01:00:45.600 align:middle line:84% And that's going to run a special script that Facebook has put together 01:00:45.600 --> 01:00:48.600 align:middle line:84% that's going to basically take care of the process of taking all 01:00:48.600 --> 01:00:51.600 align:middle line:84% this code in different files and written in JSX 01:00:51.600 --> 01:00:55.620 align:middle line:84% and compile them for me into regular JavaScript 01:00:55.620 --> 01:00:58.390 align:middle line:90% that any web server can understand. 01:00:58.390 --> 01:01:00.570 align:middle line:84% And so if I go into the build directory now, 01:01:00.570 --> 01:01:03.062 align:middle line:84% I see that I have all of these files here 01:01:03.062 --> 01:01:05.520 align:middle line:84% that are basically just going to be files that I can serve, 01:01:05.520 --> 01:01:08.062 align:middle line:84% using any old web server without the need to translate things 01:01:08.062 --> 01:01:09.390 align:middle line:90% from one language to another. 01:01:09.390 --> 01:01:10.837 align:middle line:90% And that will just work as well. 01:01:10.837 --> 01:01:13.170 align:middle line:84% So not going to delve too much into that because there's 01:01:13.170 --> 01:01:15.850 align:middle line:84% a lot of details and nuances here that are worth exploring, 01:01:15.850 --> 01:01:17.370 align:middle line:90% and this changes from time to time. 01:01:17.370 --> 01:01:19.530 align:middle line:84% But just good to be aware of, in case you 01:01:19.530 --> 01:01:24.150 align:middle line:84% decide to continue with building React applications. 01:01:24.150 --> 01:01:26.280 align:middle line:90% Questions before I go on about anything? 01:01:26.280 --> 01:01:30.000 align:middle line:90% 01:01:30.000 --> 01:01:33.243 align:middle line:84% All right, so this morning's project, you're 01:01:33.243 --> 01:01:34.660 align:middle line:90% going to have a number of options. 01:01:34.660 --> 01:01:36.445 align:middle line:84% I'm going to introduce one of them in just a moment, 01:01:36.445 --> 01:01:38.470 align:middle line:84% so we're not quite done for the morning lecture just yet. 01:01:38.470 --> 01:01:40.387 align:middle line:84% But a number of options for things you can do. 01:01:40.387 --> 01:01:43.178 align:middle line:84% One of the goals here is just to continue giving you an opportunity 01:01:43.178 --> 01:01:44.418 align:middle line:90% to continue working on React. 01:01:44.418 --> 01:01:46.960 align:middle line:84% So I know many of you are still working on or adding features 01:01:46.960 --> 01:01:49.810 align:middle line:84% to your to-do list application or your flashcards application. 01:01:49.810 --> 01:01:52.477 align:middle line:84% So if you'd like to, feel free to continue working on and adding 01:01:52.477 --> 01:01:53.628 align:middle line:90% to those applications. 01:01:53.628 --> 01:01:55.420 align:middle line:84% If you'd like an interesting new challenge, 01:01:55.420 --> 01:01:57.610 align:middle line:84% if you happen to be done with those, or you're getting bored of them 01:01:57.610 --> 01:01:59.443 align:middle line:84% and want to try something different, you can 01:01:59.443 --> 01:02:01.330 align:middle line:84% try implementing a Connect Four game, sort 01:02:01.330 --> 01:02:03.790 align:middle line:84% of an upgraded version of tic-tac-toe, this time for four 01:02:03.790 --> 01:02:04.905 align:middle line:90% in a row instead of three. 01:02:04.905 --> 01:02:07.280 align:middle line:84% But I'll show you what that looked like in just a moment. 01:02:07.280 --> 01:02:08.230 align:middle line:90% And if you'd like to-- 01:02:08.230 --> 01:02:09.400 align:middle line:90% we're on the second-to-last day now. 01:02:09.400 --> 01:02:12.910 align:middle line:84% We want to give you the flexibility to explore, the freedom to try things new. 01:02:12.910 --> 01:02:15.160 align:middle line:84% Feel free to start something new of your own choosing. 01:02:15.160 --> 01:02:18.310 align:middle line:84% Really the goal of today is to really make the focus be about project time. 01:02:18.310 --> 01:02:20.230 align:middle line:84% You've heard me talk a lot this past week. 01:02:20.230 --> 01:02:21.550 align:middle line:84% So we're going to try and talk a little bit less 01:02:21.550 --> 01:02:23.320 align:middle line:84% today and give you more of an opportunity 01:02:23.320 --> 01:02:25.570 align:middle line:84% to really try things hands on, because you've probably 01:02:25.570 --> 01:02:28.788 align:middle line:84% found by this point in time that really the best way to learn this material 01:02:28.788 --> 01:02:29.830 align:middle line:90% is to be working with it. 01:02:29.830 --> 01:02:30.760 align:middle line:90% Try things out. 01:02:30.760 --> 01:02:34.700 align:middle line:84% Try and get features to work on your own and see what happens ultimately. 01:02:34.700 --> 01:02:36.922 align:middle line:84% And so these are going to be the potential options. 01:02:36.922 --> 01:02:39.880 align:middle line:84% If you choose to implement the Connect Four game, the types of features 01:02:39.880 --> 01:02:42.370 align:middle line:84% you might want to consider, displaying a board 01:02:42.370 --> 01:02:44.710 align:middle line:90% and which player's turn it currently is. 01:02:44.710 --> 01:02:46.690 align:middle line:84% When the user clicks on a column, the turn 01:02:46.690 --> 01:02:48.940 align:middle line:84% changes from red to black or black to red, 01:02:48.940 --> 01:02:51.010 align:middle line:84% as the typical colors are for Connect Four. 01:02:51.010 --> 01:02:55.180 align:middle line:84% If you click on a column, that drops a circle inside of that column, 01:02:55.180 --> 01:02:56.278 align:middle line:90% for example. 01:02:56.278 --> 01:02:58.570 align:middle line:84% Don't allow clicking on a column that's already filled, 01:02:58.570 --> 01:03:01.753 align:middle line:84% if it's filled to the top of what's usually a seven-by-seven grid. 01:03:01.753 --> 01:03:04.670 align:middle line:84% And when someone has four in a row, you can display who the winner is. 01:03:04.670 --> 01:03:07.180 align:middle line:90% And that will probably be the last step. 01:03:07.180 --> 01:03:09.932 align:middle line:84% If you choose to try and implement this project, when it's done, 01:03:09.932 --> 01:03:12.640 align:middle line:84% it's probably going to look something-- it could look something-- 01:03:12.640 --> 01:03:19.270 align:middle line:84% a little something like this, whereby you have a Connect Four 01:03:19.270 --> 01:03:22.240 align:middle line:84% and who the current turn is in a big seven-by-seven grid. 01:03:22.240 --> 01:03:24.910 align:middle line:84% And this, again, could just be an HTML table, for example. 01:03:24.910 --> 01:03:28.180 align:middle line:84% I've implemented on mine some additional features 01:03:28.180 --> 01:03:30.100 align:middle line:84% for detecting when the mouse is happening. 01:03:30.100 --> 01:03:31.810 align:middle line:90% And there are things like onMouseEnter. 01:03:31.810 --> 01:03:33.440 align:middle line:84% There's event handlers you can do for that 01:03:33.440 --> 01:03:36.130 align:middle line:84% so that when you hover over columns, that you can see the column 01:03:36.130 --> 01:03:38.630 align:middle line:84% highlighted, though you don't need to implement the feature, 01:03:38.630 --> 01:03:40.450 align:middle line:90% at least not initially. 01:03:40.450 --> 01:03:44.440 align:middle line:84% You click on a column, and, OK, that drops a red circle into that column. 01:03:44.440 --> 01:03:46.030 align:middle line:90% And, OK, now it's black's turn. 01:03:46.030 --> 01:03:49.660 align:middle line:84% And so black can click somewhere in order to play a black circle there. 01:03:49.660 --> 01:03:54.130 align:middle line:84% And we can continue this game until someone gets four in a row. 01:03:54.130 --> 01:03:58.120 align:middle line:84% And when someone gets four in a row, the winner of the game is black, 01:03:58.120 --> 01:04:00.010 align:middle line:90% and we display who the winner is then. 01:04:00.010 --> 01:04:01.900 align:middle line:84% So an option for something that you can try 01:04:01.900 --> 01:04:04.690 align:middle line:84% to implement if you're looking for an interesting challenge. 01:04:04.690 --> 01:04:08.020 align:middle line:84% And let's think about the type of state that you probably want 01:04:08.020 --> 01:04:10.900 align:middle line:90% to store inside of this application. 01:04:10.900 --> 01:04:12.700 align:middle line:90% What state would you want to store? 01:04:12.700 --> 01:04:14.200 align:middle line:84% So even if you're not planning on programming 01:04:14.200 --> 01:04:15.575 align:middle line:90% this, let's at least plan it out. 01:04:15.575 --> 01:04:16.420 align:middle line:90% Think in React. 01:04:16.420 --> 01:04:19.210 align:middle line:84% Think in our minds about what the state of this looks like, 01:04:19.210 --> 01:04:21.640 align:middle line:84% what sort of event handlers we would need for it, 01:04:21.640 --> 01:04:23.390 align:middle line:84% what is the structure this is going to be? 01:04:23.390 --> 01:04:24.094 align:middle line:90% Yeah? 01:04:24.094 --> 01:04:27.273 align:middle line:90% AUDIENCE: [INAUDIBLE] 01:04:27.273 --> 01:04:29.440 align:middle line:84% SPEAKER: Yeah, a list of lists probably makes sense. 01:04:29.440 --> 01:04:30.880 align:middle line:90% We've got a seven-by-seven grid. 01:04:30.880 --> 01:04:33.088 align:middle line:84% And you have this interesting idea, which is probably 01:04:33.088 --> 01:04:35.020 align:middle line:84% a good one, which is that each list might 01:04:35.020 --> 01:04:38.020 align:middle line:84% want to be a list of all of the columns, like a column 01:04:38.020 --> 01:04:41.290 align:middle line:84% of lists for the first column, the second column, the third column. 01:04:41.290 --> 01:04:45.310 align:middle line:84% Because that's going to make it easy to implement the idea of dropping 01:04:45.310 --> 01:04:48.400 align:middle line:84% a circle into one of the columns, where if we have this 01:04:48.400 --> 01:04:51.220 align:middle line:84% is just like an array that is black and then red, 01:04:51.220 --> 01:04:53.470 align:middle line:84% if I try and add something to this column, 01:04:53.470 --> 01:04:56.980 align:middle line:84% it's as simple as just appending something to the end of that array, 01:04:56.980 --> 01:04:57.610 align:middle line:90% for instance. 01:04:57.610 --> 01:04:59.020 align:middle line:90% You just add to that array. 01:04:59.020 --> 01:05:01.360 align:middle line:84% And that's going to result in this being reflected. 01:05:01.360 --> 01:05:05.028 align:middle line:84% Now, if you design it with each column being a different array 01:05:05.028 --> 01:05:07.570 align:middle line:84% inside of your application, you'll need to think a little bit 01:05:07.570 --> 01:05:10.887 align:middle line:84% about how to make rows appear inside of your table, for instance. 01:05:10.887 --> 01:05:12.220 align:middle line:90% But, yeah, that's good thinking. 01:05:12.220 --> 01:05:15.477 align:middle line:84% So an array of arrays storing in the state 01:05:15.477 --> 01:05:17.560 align:middle line:84% to store the current state of the board, what else 01:05:17.560 --> 01:05:19.352 align:middle line:84% are we going to need to store in the state? 01:05:19.352 --> 01:05:20.790 align:middle line:90% 01:05:20.790 --> 01:05:22.540 align:middle line:84% Whose turn it is, great, is it red's turn? 01:05:22.540 --> 01:05:26.320 align:middle line:84% Is it a black's turn probably also something you want to store as well. 01:05:26.320 --> 01:05:30.190 align:middle line:84% And what sort of event handlers do we need on this board? 01:05:30.190 --> 01:05:34.600 align:middle line:90% 01:05:34.600 --> 01:05:36.682 align:middle line:84% How does the user interact with this page? 01:05:36.682 --> 01:05:38.140 align:middle line:90% We've seen a lot of event handlers. 01:05:38.140 --> 01:05:41.290 align:middle line:84% We've seen the onChange event Handler for when someone typed something 01:05:41.290 --> 01:05:44.470 align:middle line:90% into an input field, for example. 01:05:44.470 --> 01:05:46.730 align:middle line:84% What else have we seen that might be useful here? 01:05:46.730 --> 01:05:47.710 align:middle line:90% AUDIENCE: [INAUDIBLE] 01:05:47.710 --> 01:05:48.710 align:middle line:90% SPEAKER: On click, yeah. 01:05:48.710 --> 01:05:50.000 align:middle line:84% And you probably want something like that, 01:05:50.000 --> 01:05:52.040 align:middle line:84% that for each of these table cells, we have 01:05:52.040 --> 01:05:55.680 align:middle line:84% some sort of on-click mechanism for if you click on this table cell, 01:05:55.680 --> 01:05:59.065 align:middle line:84% well, that's going to correspond to dropping something in this column. 01:05:59.065 --> 01:06:01.940 align:middle line:84% And there's probably no difference between clicking here and clicking 01:06:01.940 --> 01:06:02.240 align:middle line:90% here. 01:06:02.240 --> 01:06:04.310 align:middle line:84% Because either way, it's still clicking inside 01:06:04.310 --> 01:06:06.860 align:middle line:84% of the same column, given the nature of the game. 01:06:06.860 --> 01:06:09.800 align:middle line:84% And so you can think about, all right, when someone clicks on a cell, 01:06:09.800 --> 01:06:13.340 align:middle line:84% you probably want to ask a question, OK, what column is it in? 01:06:13.340 --> 01:06:16.820 align:middle line:84% Then you might want to ask a question like, is the column already filled? 01:06:16.820 --> 01:06:19.340 align:middle line:84% In which case, well, we can't add anything more to it. 01:06:19.340 --> 01:06:21.860 align:middle line:84% But if it's not already filled, then we can say something. 01:06:21.860 --> 01:06:27.380 align:middle line:84% All right, let's go ahead and add something to that particular array 01:06:27.380 --> 01:06:29.200 align:middle line:90% inside of our application state. 01:06:29.200 --> 01:06:32.450 align:middle line:84% So these are the sorts of questions, the sorts of things to be thinking about. 01:06:32.450 --> 01:06:34.825 align:middle line:84% Before you even write a single line of code, think about, 01:06:34.825 --> 01:06:36.650 align:middle line:84% what are the components of the application? 01:06:36.650 --> 01:06:38.780 align:middle line:84% What is the state of the application going to look like? 01:06:38.780 --> 01:06:40.880 align:middle line:84% What sort of event handlers are you going to need? 01:06:40.880 --> 01:06:43.810 align:middle line:84% And this is the way to begin thinking about things inside of React. 01:06:43.810 --> 01:06:44.446 align:middle line:90% Yeah? 01:06:44.446 --> 01:06:46.876 align:middle line:90% AUDIENCE: Is that [INAUDIBLE]? 01:06:46.876 --> 01:06:50.770 align:middle line:90% Or is [INAUDIBLE]? 01:06:50.770 --> 01:06:51.910 align:middle line:90% SPEAKER: Good question. 01:06:51.910 --> 01:06:53.743 align:middle line:84% The way I have implemented this, and the way 01:06:53.743 --> 01:06:57.190 align:middle line:84% you can certainly consider doing it, is this is just an HTML table. 01:06:57.190 --> 01:07:01.540 align:middle line:84% But inside of each table cell, I've inserted an SVG target, inside 01:07:01.540 --> 01:07:04.030 align:middle line:84% of which is just going to be an SVG circle. 01:07:04.030 --> 01:07:06.760 align:middle line:84% And as you remember, a circle just has the center x-coordinate, 01:07:06.760 --> 01:07:09.800 align:middle line:84% center y-coordinate, radius, and also a fill color. 01:07:09.800 --> 01:07:13.830 align:middle line:84% And these are just fill color red and fill color black. 01:07:13.830 --> 01:07:17.450 align:middle line:84% And if you really want to get fancy and implement the hover feature, 01:07:17.450 --> 01:07:21.800 align:middle line:84% all the hover feature is, is when you're hovering over a column, let's go ahead 01:07:21.800 --> 01:07:23.630 align:middle line:90% and turn the cells gray. 01:07:23.630 --> 01:07:27.440 align:middle line:84% And if there's nothing in a cell, rather than having nothing there, 01:07:27.440 --> 01:07:30.920 align:middle line:84% have a white circle instead of a red circle or a black circle. 01:07:30.920 --> 01:07:33.020 align:middle line:84% And by doing that, you're able to get this effect 01:07:33.020 --> 01:07:37.730 align:middle line:84% of this hover, where there's just white circles across the entire grid. 01:07:37.730 --> 01:07:40.490 align:middle line:84% But when you hover over a column, the background turns gray. 01:07:40.490 --> 01:07:42.560 align:middle line:84% And so you get the effect that you might expect, 01:07:42.560 --> 01:07:44.477 align:middle line:84% that looks visually interesting, but really is 01:07:44.477 --> 01:07:47.240 align:middle line:84% just a bunch of circles and colors changing 01:07:47.240 --> 01:07:49.840 align:middle line:84% in terms of the way this is actually implemented. 01:07:49.840 --> 01:07:51.840 align:middle line:84% If you're looking for a simpler version of this, 01:07:51.840 --> 01:07:54.048 align:middle line:84% feel free to try and take the tic-tac-toe application 01:07:54.048 --> 01:07:57.080 align:middle line:84% that we originally made in Flask and just reemployment that using React. 01:07:57.080 --> 01:07:59.610 align:middle line:84% And that might be a good starting point as a place to begin 01:07:59.610 --> 01:08:01.160 align:middle line:84% and then building up to something like this. 01:08:01.160 --> 01:08:02.702 align:middle line:90% But there are a lot of possibilities. 01:08:02.702 --> 01:08:06.170 align:middle line:84% And so goal for today is really to give you a lot of time for hands-on practice 01:08:06.170 --> 01:08:07.870 align:middle line:90% in order to work on that. 01:08:07.870 --> 01:08:09.740 align:middle line:90% So questions about morning project? 01:08:09.740 --> 01:08:13.910 align:middle line:90% 01:08:13.910 --> 01:08:16.620 align:middle line:84% All right, so a couple things on a logistical note. 01:08:16.620 --> 01:08:19.107 align:middle line:84% So we only have today and tomorrow left in CS50 Beyond. 01:08:19.107 --> 01:08:21.899 align:middle line:84% Just see you all know, tomorrow's probably going to be a short day. 01:08:21.899 --> 01:08:24.899 align:middle line:84% We're probably going to wrap up probably around mid-day 01:08:24.899 --> 01:08:28.710 align:middle line:84% and not have an afternoon session tomorrow, so wrap a bit early, give you 01:08:28.710 --> 01:08:32.490 align:middle line:84% most of Friday to have off in order to enjoy the weekend before classes 01:08:32.490 --> 01:08:33.779 align:middle line:90% begin again on Monday. 01:08:33.779 --> 01:08:36.990 align:middle line:84% And one other thing that I'd like to ask you all to do before you-- 01:08:36.990 --> 01:08:39.479 align:middle line:84% right now before you actually start working on the morning 01:08:39.479 --> 01:08:43.859 align:middle line:84% project is to fill out our feedback form. 01:08:43.859 --> 01:08:46.990 align:middle line:84% So just try and get this some feedback before the course is over. 01:08:46.990 --> 01:08:50.797 align:middle line:84% If you go to cs50.ly/feedback, you'll find an anonymous feedback form, 01:08:50.797 --> 01:08:53.880 align:middle line:84% where you can leave anonymous feedback about your experience in this class 01:08:53.880 --> 01:08:55.529 align:middle line:90% over the course of this week. 01:08:55.529 --> 01:08:58.033 align:middle line:84% Goal for this is just very good useful data for us 01:08:58.033 --> 01:08:59.950 align:middle line:84% in order to be able to help improve the class. 01:08:59.950 --> 01:09:02.689 align:middle line:84% This is the first time that we are offering CS50 Beyond. 01:09:02.689 --> 01:09:05.609 align:middle line:84% And so all of this is sort of brand-new curriculum and content 01:09:05.609 --> 01:09:06.359 align:middle line:90% and organization. 01:09:06.359 --> 01:09:09.359 align:middle line:84% So curious to get your impressions on what you think the strengths were, 01:09:09.359 --> 01:09:11.279 align:middle line:84% what things you would change, or what things you would recommend 01:09:11.279 --> 01:09:12.630 align:middle line:90% as improvements for the future. 01:09:12.630 --> 01:09:15.240 align:middle line:84% We'll definitely read all of this feedback, and so all of it 01:09:15.240 --> 01:09:16.710 align:middle line:90% would definitely be very helpful. 01:09:16.710 --> 01:09:18.930 align:middle line:84% So please go ahead and fill out this feedback form. 01:09:18.930 --> 01:09:20.910 align:middle line:84% When it's done, feel free to dive into your projects. 01:09:20.910 --> 01:09:23.952 align:middle line:84% We'll work on these projects now in the morning, here in this auditorium, 01:09:23.952 --> 01:09:26.520 align:middle line:84% until about 12:30, at which point we'll break for lunch. 01:09:26.520 --> 01:09:28.687 align:middle line:84% We'll come back at 2:00 for a couple of more points, 01:09:28.687 --> 01:09:31.470 align:middle line:84% but mostly to spend the afternoon focused on working on projects. 01:09:31.470 --> 01:09:35.600 align:middle line:84% And so we'll break for now and let you work on those projects. 01:09:35.600 --> 01:09:36.781 align:middle line:90%