‫In this lecture
‫we're finally going to build a brand new feature for our app
‫which is to persist the watch list in local storage.
‫So right now, if we have some movies here in our watch list
‫and if we then reload the page, then you see
‫that of course our movies are going to be gone.
‫So they're not persisted, so they're not stored anywhere.
‫And so that's why in this lecture
‫we will now use local storage to store
‫this watched data information in the browser.
‫So we're going to do this in two parts.
‫First, each time that the watch list state is updated
‫we will update the local storage.
‫So we will store that data into local storage
‫and then each time that the application loads
‫so when the app component first mounts
‫we will read that data from local storage
‫and store it into the watched state.
‫So let's do that starting with the first part
‫which is to store the watched movies here
‫into local storage each time that they are updated.
‫And we can actually do that in two different ways
‫or in two different places.
‫So the first option is to store that data
‫into local storage each time
‫that a new movie is actually added.
‫So basically right here in this event handler function
‫that is responsible for adding new movies to the watch list.
‫So each time that happens
‫we can then store the new watch list into local storage.
‫So that's the first option.
‫And the second option is to simply do it in an effect.
‫And so let's actually do both of them
‫starting here in this event handler function.
‫Now by the way, if you're not familiar with local storage
‫it's basically just a very simple key value pair storage
‫that is available in the browser
‫and where we can store some data for each domain.
‫So basically the data that we store
‫in local storage now will only be available
‫through exactly this URL right here,
‫not for example in this other one.
‫Alright? And the way we use local storage
‫is simply calling local storage
‫which is a function available in all browsers.
‫And then we set item,
‫then we pass in the name of the key
‫so basically the name of the data that we want to store
‫and then second, the actual data.
‫Now here, we cannot simply use the watched array
‫like this because it has just been updated here.
‫And so as we already know
‫this updating happens in an asynchronous way.
‫And so therefore right here, this is still stale state.
‫So it's basically still the old version
‫before a new movie has been added.
‫And so we need to basically do the same thing as here.
‫So we need to build a new array based on the watched
‫so the current state plus the new movie.
‫And then finally, we need to convert all of this
‫into a string because in local storage,
‫we can only store key value pairs
‫where the value is a string.
‫And so let's use the built-in JSON.stringify.
‫Now alright? And this should now actually work.
‫Let's try some different movies now here.
‫So let's try this one
‫which is actually one of my all time favorite movies.
‫So let's add that to the list
‫and maybe another one now, right?
‫And so now we have our two movies in the list,
‫but of course if we reload the page now
‫they will not magically appear back in the UI,
‫but we can still check if they have been stored
‫into local storage.
‫So in the DevTools again
‫we just come here to application.
‫And then here on the left side
‫you should have this local storage thing.
‫And so indeed here we see that our array
‫of watched movies has indeed been stored into local storage.
‫Great. So that's working.
‫But as I was saying
‫we can also do it right inside in effect.
‫So instead of doing it here in the event handler function,
‫and we will actually do it in an effect
‫instead of here in this event handler function
‫because later in the section we will want to make
‫this storing data into local storage, reusable.
‫So let's just comment this out
‫and then let's come down here and create a new effect.
‫So you see that I like to have always the states
‫here in the beginning of the components.
‫Then the event handler functions
‫which update some of the state.
‫And then in the end, the effects.
‫So let's create a new effect with the function,
‫and then as we were just saying, we want this effect
‫to run each time Dev to watched movies are updated.
‫And so then here we can very easily, let's just
‫grab this first part here, or actually all of it.
‫So let's paste that here.
‫And now we don't have to create any new array
‫because this effect here will only run after the movies
‫have already been updated.
‫So after watched is already the new state.
‫And so we can then simply use that here.
‫All right, let's reload.
‫And we see that our local storage has already been updated
‫and that's because this effect here
‫run when the component was first mounted.
‫And so at this point the watched state is by default
‫still this empty array.
‫And so then React set that here to the empty array.
‫So let's just try, oh, that's not correct.
‫And for some reason here
‫the loading state is no longer working
‫but let's take a look at that later.
‫So as we add new movies to the list now
‫we should see our local storage being updated.
‫Nice, so that part is working
‫and so now we need to take care of the second part
‫which is to read this data back
‫into the application as soon as the app component mounts.
‫So the component that owns this watched state.
‫Now how can we do that?
‫Well, we might think that we should use another effect
‫in order to get the data from local storage
‫on the initial render
‫and then store that data in the watched state.
‫However, there is actually a better way.
‫And so let me show that to you.
‫So let's deactivate this watched state here
‫and maybe let's move it down here and then duplicate it
‫because we still need this state of course.
‫So what we're going to do now is to,
‫instead of just passing in a value
‫is to pass in a callback function.
‫And so that's because the useState hook
‫also accepts a callback function instead
‫of just a single value.
‫And so we can then initialize the state
‫with whatever value this callback function will return.
‫And so let's try that out.
‫So let's pass in a function here.
‫So creating a brand new function.
‫And so then let's create a new variable
‫let's say storage, value,
‫and then we can just read from local storage
‫with the get item method.
‫So get item and then the key that we used before
‫to store the data in local storage.
‫So that's this key right here.
‫And so then we just need to return this value.
‫And so again, React will then call this function here
‫on the initial render and we'll use
‫whatever value is returned from this function
‫as the initial value of the state.
‫And this function here actually needs to be a pure function
‫and it cannot receive any arguments.
‫So passing arguments here is not going to work.
‫So just a very simple pure function that returns something
‫and that something will be used by React
‫as the initial state.
‫And also just like the values that we pass in,
‫React will only consider this function here
‫on the initial render.
‫So this function is only executed once on the initial render
‫and is simply ignored on subsequent re-renders.
‫Now, apparently there is some problem here
‫so let's check that out.
‫So watched map is not a function
‫and I actually saw that coming because
‫right now the local storage here is a string.
‫So remember that we stored the data
‫as a string by doing JSON.stringify
‫and then when we get the data back
‫we need to convert it back by doing JSON.parse.
‫Alright and beautiful.
‫So here, the movie that we added to our watch list before
‫is now indeed back in our watch list
‫after reloading the page.
‫So we successfully stored the data
‫in local storage and retrieved it as the application loads.
‫So our callback function here is doing its job.
‫And so this creates a much better experience for the user.
‫So whenever the initial value of the use data
‫depends on some sort of computation
‫we should always pass in a function like this.
‫So function that React can execute on its initial render.
‫So we should not call a function inside useState.
‫So we should not do this, okay?
‫So this is very different.
‫Here we are calling a function, not passing a function in.
‫And so this we should not do
‫because even though React would ignore the value of this
‫it would still call this function on every render
‫which is not good.
‫So never do this and instead pass in a function
‫that React can then call later.
‫Now okay, now let's again go back to our application
‫tap here, because now we want to see what happens
‫when we delete a movie from here,
‫and you see that it actually automatically got removed
‫here from the local storage as well.
‫So why is that?
‫Well, it's because thanks to our effect here
‫we have effectively synchronized the watched state
‫with our local storage.
‫So when the watched state changes,
‫our local storage changes as well.
‫And so this is a great advantage
‫of having used the useEffect hook
‫instead of setting local stage right here
‫in the event handler, because if we had done it
‫like this here, then we would also have to manually
‫set the local storage here as we deleted a movie.
‫So here we would then also have to do the exact same thing
‫and use all this here as the new local storage.
‫But so now since we have basically synchronized
‫the two of them, we no longer need to do that.
‫Alright, now let's just see what happens
‫when we reload the page and everything's working fine.
‫Let's just do one more test,
‫add a few more movies to our list.
‫Of course, this is a 10, not some other value.
‫Now, okay, now I see we are getting some errors here
‫but maybe that was ah,
‫that's because of the image not loading.
‫And now when I reload, ah, beautiful!
‫Both our movies are still in the list.
‫So we learned here yet another way of using
‫the useState hook.
‫So now we know that besides passing in a single value
‫we can also pass in a callback function.
‫So this all can be a little bit confusing
‫with all these different options that we have.
‫And so in the next lecture, we will basically
‫summarize everything that we know about the useState hook
‫since that is such an important talk in React development.