Transcript from the "Persisting Data & Async Storage" Lesson
>> So, now we have built a app where you can choose moods and we have a history tab where you can see past moods. But you will notice that if I reload our app then the history is wiped and obviously this is not very handy because I would like to have an actual history of my moods.
[00:00:38] On the web, you're probably already familiar with local storage and there is an equivalent in React Native is called async storage. It kind of works the same way as local storage but the difference is that it is as the name suggests, asynchronous. Anything that you store in local storage has to be serializable and in layman's terms, this basically means you can't store objects or functions, or anything like that, or classes or references.
[00:01:06] So, it needs to be stringed in numbers because we call to string on the value that we're going to store. Async storage is a native library, so let's copy this install command and we'll open a terminal and install the library And for iOS we'll cd into the ios directory and pod install.
[00:01:42] So, you'll see the library that's going to install. And let's go back to our root directory and run yarn ios or you can always run your app through X code instead. For Android, there's no need to install packages just rebuild your app using yarn Android or rebuild via Android Studio.
[00:02:04] So, stop and restart, so, for the API for async storage is pretty straightforward, so if we look at the docs. We have getItem, setItem, mergeItem, removeItem, getAllKeys and clear, which are the ones that I'm mostly ends up using. So, let's look at the function signatures. So, get item, you pass in a string key, so this will be sandboxed kind of so it will be scoped to your app.
[00:02:45] So, for example, you wouldn't be able to get the item from another apps async storage. So, this works similarly to local storage, so you'll get the item by key. And usually we will store things by JSON but you can just store individual strings as well and then we get the value.
[00:03:04] For setItem, it's pretty much the same, but we just set the Item by key. So, we take in two arguments, the first one is the key and the second one is the value that you want to set. So, this value needs to be a string. Then we have clear to clear the whole async storage.
[00:03:21] You have removeItem to remove this particular Item and another handy one is getAllKeys. So, this is get all of the keys that are ever set for this app. Let's see if the build has finished, excellent timing. All right, so if we go to our app provider, let's start by importing async storage, From React Native, I think it's a React Native community package.
[00:03:57] There it is, so React Native async storage, async storage. And I'm just gonna quickly check where I called the functions, so I'll be consistent. Okay, so let's figure out what we want our app data to look like. So, let's do type app data. And we just wanna store the mood list.
[00:04:27] Which will be a mood option with timestamp. So, generally things that you store in async storage, it's good to have them as JSON objects because then you can always add keys and let's also do it a constant for our key. So, let's call it my app data. What data key, let's do a set app data.
[00:05:03] So, this takes in the app data that we want to save. We should be of type app data and it doesn't return anything so we use void. So, to do this we'll do const results equals async storage dot setItem and we'll use the data key. And we'll JSON stringify our app data, now this is an async function, so I want to await it.
[00:05:47] So, I need to make this into an async arrow function. Okay and this is actually telling me that, you said there's going to return void but actually it's a promise, so I'm going to add promise. So, it's asynchronous and then is going to returning nothing And we don't actually need the result.
[00:06:46] I'm kind of not doing anything with it. All right, let's do another one for actually getting the app data. So, const get app data so this will also be an async function. We don't have any arguments but it returns a promise with app data. And let's do another try-catch here.
[00:07:20] I will do a const of results, I will await async storage getItem. So, this is why it's nice to pull these out to a constant, just to make sure that we use the same key. And that's it. So, this gives us the results and we'll also because we JSON stringfied our app data here, we want to JSON pass the results.
[00:07:49] So, we'll do return but we also need to account for when the result is undefined. So, we'll do if result, Because obviously on initial launch this will just be no, return JSON parse and result. Okay, and we also need a default value, so let's do return null by default.
[00:08:23] And we'd also need to tell our promise that we do this. So, just as a side note about TypeScript, so I don't actually need to type these return types. So, if I hover over this, you can look at the function signature so it goes, okay takes up data and returns an empty promise.
[00:08:44] If I remove this this is where the static code checking comes to play, if I remove this and hover over it, TypeScript only knows this. So, actually this return type is superfluous which is quite handy, so it can be nice to add it just to sanity check your things.
[00:09:04] Or if it's not returning what you thought it was returning but in this case we don't actually need to explicitly type it. I was just looking in get app data, here we kind of do want to say that if it's app data or no. So, if we don't type it and see that it's going to say, it returns a promise of any, which isn't correct.
[00:09:24] So, in this case we want to type it, that's a good example again. And then in this case, it doesn't matter because we return nothing. Cool, so we want to get and set this on launch. So, let's do a use effect. So, if we do a use effect with an empty dependency array, it gets run at launch.
[00:09:50] And so, in use effect you can't run asynchronous functions but obviously this is asynchronous. So, way around it is you can define an asynchronous function inside your use effect and just call it. So, let's do fetch app data, this will be an async function. And we'll do const data equals get app data.
[00:10:19] So, this will be async so we need to await it. And if data remember the default value for it is no, then we set the mood list to be data dot mood list. And here let's just call fetch app data. So, that's to get the initial data but we also need to save the data whenever we make a change.
[00:10:51] So, just a quick way of doing it is, I'm going to do it inside this handle select mood callback. So, let's make this not an implicit return, so I make this into an explicit return and do const new mood list which will be this value, so we still want to return it.
[00:11:19] But also, before we return it let's set app data and let's do a mood list to be the new mood list Alright that should be all the vets let's reload to be clear and let's add some moods, so we've got two mood here. And let's reload and they're still there.
[00:11:47] Now, if I actually completely close the app and reopen it, they're still there so they are get persisted across launches.