Placeholder Image

字幕列表 影片播放

  • [PIANO PLAYING]

  • SPEAKER: OK, let's get started.

  • Welcome back, everyone, to CS50 Beyond.

  • Our goal for today--

  • this is the second-to-last day of the course.

  • And goal for today is going to be to pick up really

  • where we left off yesterday.

  • So yesterday we introduced a new JavaScript library called React.

  • And React was designed to make it easier for us to build

  • interactive and dynamic web pages.

  • And we did so by creating components and ultimately via declarative programming,

  • where we were describing what it is that the page should look like,

  • whether certain variables should belong in certain places on the page,

  • whether we should be iterating over a particular variable in order

  • to display a list of things on the page.

  • And then the only thing we needed to do in order to edit the page was

  • rather than go into the dom and manipulate the dom and say,

  • update this element or update that element, we would just say,

  • change the data.

  • Set the state of the component to be something different.

  • And the page would automatically render and re-update

  • the parts of the page that needed to in order to reflect those changes.

  • And so the goal of today is to continue along those lines and in particular,

  • emphasize thinking in React, thinking about how

  • it is that we take an application that we're going for,

  • decompose it into pieces, and then try and put it back together, such

  • that we can figure out what components, what state we

  • need to keep track of in order to make our applications

  • interactive and useful.

  • Along the way we'll talk about things like React lifecycle

  • and about how to get your React applications, which

  • are front-end applications, to interact with the back end, like a server,

  • for instance, connecting to APIs then.

  • And then we'll have some opportunity for hands-on projects, as before.

  • And so we'll start by taking a look at an example from yesterday

  • and begin to answer some of the questions

  • that yesterday I pushed off until today.

  • And so we'll take a look at counter.html And counter.html,

  • you'll recall from yesterday, was just an application

  • whereby it displayed a number that defaulted to the number 0.

  • And then we had increment and decrement buttons, or plus and minus buttons,

  • where all those buttons' data will change the value of the number.

  • We started with 0.

  • We can go 1, 2, 3, 4, 5 by clicking the Increment button plus the Minus button

  • in order to go back down.

  • And ultimately the way that we implemented

  • that program was to say inside of counter.html,

  • we had some state inside of our counter component

  • that initially was just set to the number 0.

  • And then when we click the On-click button for the plus or minus buttons,

  • we would call the increment or decrement functions.

  • And all those increment and decrement functions would do

  • is call the this.setState method, which is a special method in React that

  • takes the state and updates it, in particular by taking the count

  • and setting it to whatever the count minus 1 is in the case of decrement,

  • and in the case of increment, taking the count and adding 1 to it.

  • Of course, this state only exists when this component

  • is loaded onto the screen.

  • And as soon as we close the page and reopen it,

  • we're getting a brand-fresh, new component.

  • It's remount onto the screen.

  • And as a result, if I increase the number to, say, 5, for example,

  • close the page, and then reopen the counter.html, we're back to 0, right?

  • We reloaded the page.

  • The JavaScript is rerun.

  • And as a result, our state is reset back to the initial state

  • as defined by the constructor, which, in this case, is the number 0.

  • Now, before we got to the world of React and we were just

  • dealing with plain JavaScript, how do we solve this problem,

  • if we wanted the state to persist between when you open the page,

  • closed the page, open it again?

  • We cached it in a place called local storage,

  • a place within the browser, whereby we could

  • say I want to store the state of the application inside of local storage,

  • such that later on in my application I can refer back to local storage

  • and say, get this value out of local storage and put it into my application.

  • And in React, we can do something very similar.

  • Every React component has a number of what are called lifecycle methods,

  • or functions that are going to run at a particular point in the component's

  • life.

  • And one of the most common is a special function

  • in React called componentDidMount.

  • There are a number of others.

  • The only one we're going to talk about today is componentDidMount

  • And componentDidMount is a special method in React

  • that is going to run as soon as a component is mounted into the dom.

  • In other words, as soon as we add this component into the dom,

  • this is the method that's going to run before it actually ultimately renders

  • the contents of what's going to show up.

  • So any work we want to do of, like, setting up the component,

  • we can do inside of componentDidMount.

  • And so one thing we can do, for example, is get something out of local storage.

  • I can say, local storage.getItem count in order

  • to say, all right, let me get the count value out of local storage.

  • And I'll save that inside of a variable that I'm just going to call count.

  • So if there was an item called count in local storage,

  • I'm going to extract it from local storage

  • and save it inside of a variable called count.

  • Now, there's a chance that there was no count item in local storage,

  • that this is not equal to any particular value.

  • And so it's possible that count is going to be equal to null.

  • So let me just do a check.

  • Let me check if count is not equal to null,

  • meaning there actually was some count saved inside of local storage,

  • well, then what I'm going to do is I'm going

  • to call this.setState, setting the count equal to the result of parse int count.

  • It's going to be stored as a string so we'll parse it as an integer

  • in order to update the state of the application.

  • So componentDidMount, if you think about the chronology of things,

  • is going to happen after we've constructed this component

  • and inserted it into the dom.

  • And we want some initial code to be running

  • at the beginning of this component's life,

  • whereby we're saying from local storage, let's extract the counter variable.

  • And as long as it's not null, then go ahead and update the state,

  • setting count equal to the result of parsing

  • the int of whatever the value of the count variable is.

  • So now we have a component that can read from local storage

  • and update its initial state based on that information.

  • What's the missing half of this now?

  • Yeah?

  • AUDIENCE: [INAUDIBLE] isn't count equal to count?

  • Why [INAUDIBLE]?

  • SPEAKER: So the way local storage is going

  • to store things is it's going to store the values of strings.

  • And so that's the way that most browsers choose to implement local storage.

  • And so when we read them from local storage,

  • we have to assume that what's coming into us will be strings.

  • And so we can parse them into integers in order to be able to use them.

  • So we've got saving things-- or retrieving things from local storage.

  • And now that I just gave away the missing piece of this

  • is saving things into local storage, whereby we're getting the item count,

  • but we're never setting the item count.

  • And so we want this to happen before the window goes away.

  • If ever I try to close the window, we want something to happen there.

  • And so we'd like to add some sort of event listener

  • for when I try to close the window, for example.

  • And oftentimes you might see other web applications

  • that have implemented something similar, whereby

  • if you try to exit out of a web document before saving,

  • you might get a warning message that says,

  • are you sure you want to leave this page without saving your changes,

  • for example.

  • Or you haven't completed this action.

  • Are you sure you want to do this thing?

  • And so just in the same way that we were able to add event listeners to when

  • the dom is done loading or when you click on a button,

  • we can also add an event listener to the window

  • to say, like, before this window's contents are unloaded,

  • let's run some particular code.

  • And so to do that, I'll say window.addEventListener.

  • And the name of this event that we're going to be using

  • is a special event called before unload.

  • In other words, before this window's contents are unloaded,

  • let's run some code.

  • Before we get rid of this component, let's run a function.

  • And that function is going to say local storage.setItem.

  • And then setItem, again, takes two arguments.

  • The first is the key, the name of the thing that we're setting.

  • And the second is the value, what value it should take on.

  • The key, as with line 22, we got the item with key count.

  • So we should be setting the item with key count.

  • And what is the value?

  • What should we be setting count equal to?

  • Yeah?

  • AUDIENCE: This.state.count?

  • SPEAKER: This.state.count, perfect.

  • We want to set count equal to whatever the current value of count

  • is inside of this component state.

  • To get to this component state, we can say

  • this.state to get at the state of the component

  • and then dot count it to say, all right, let's go into the state,

  • extract the thing with the key count, and use that as the value

  • that we save into local storage.

  • And so assuming I didn't make any mistakes here,

  • if I go back to the page, refresh the page,

  • I can increment the counter 1, 2, 3, 4, 5.

  • And now if I close the counter, that's going

  • to trigger the window.beforeUnload event, which

  • is going to save the number 5 into local storage.

  • And if I open counter.html again, press Return, all right, great,

  • the component now shows me the number 5.

  • It's been able to save that state inside of local storage,

  • such that even when I closed the page and open it back up again,

  • I've been able to maintain the state of the application.

  • Yeah?

  • AUDIENCE: [INAUDIBLE]

  • SPEAKER: For refreshing the page as well?

  • Yeah, if you refresh the page, if I go to 10, for example, and click Refresh,

  • it stays at 10 because before the contents of the page

  • are unloaded before the refresh, it's going to trigger that event listener.

  • Yeah?

  • AUDIENCE: Are the items that are kept in local storage--

  • like say you want [INAUDIBLE] the program [INAUDIBLE]..

  • Are the items in local storage, are they secure from--

  • if someone hacked into your code, broke in, could they get into it?

  • SPEAKER: The items inside of local storage

  • are actually quite accessible to anyone.

  • So anyone who could get access to the browser could get access to it,

  • insofar as all I need to do is go into inspect, and I can go into, I think,

  • it's application, at least in Chrome, and go to local storage.

  • And over here I see a count and also a counter from a previous time

  • that I was doing an application with local storage.

  • So these values are highly accessible.

  • And you can edit them as well.

  • And so probably best not to store anything super secure inside

  • of local storage for that reason.

  • You'll probably want to store things on the server side.

  • And we'll talk about interaction with server side in just a moment.

  • Yeah?

  • AUDIENCE: Will you let me know the website [INAUDIBLE]

  • variables that you put in local storage [INAUDIBLE]??

  • SPEAKER: Local storage is domain specific.

  • So if you have domain1.com, and you're storing things inside of local storage,

  • domain2.com is going to have access to a different local storage.

  • And so those are kept separate.

  • AUDIENCE: Is there a way to make it so local pages use the same [INAUDIBLE]??

  • SPEAKER: So, yeah, if they're within the same domain,

  • they can use the same local storage.

  • For example, if I were to create another file--

  • and I'll just demonstrate.

  • Like, if I just copy counter.html and call it, like, newcounter.html,

  • which is a different file, and I open up newcounter.html,

  • it's still going to have access to that same local storage.

  • It still has access to the number 10.

  • So it can draw up on those same values.

  • Other things?

  • Yeah?

  • AUDIENCE: Can you just explain a little bit more of the difference

  • between componentDidMount and why do we need didMount [INAUDIBLE]??

  • SPEAKER: Yeah.

  • So componentDidMount, there are a number of what

  • are called lifecycle methods in React, which are canonical places where you

  • can put code, and you can guarantee that React