Check out a free preview of the full Intermediate React Native, v2 course
The "Saving Plant Data" Lesson is part of the full, Intermediate React Native, v2 course featured in this preview video. Here's what you'd learn in this lesson:
Kadi explains that photos selected from the device are saved in a temporary cache that does not persist. To fix this, the newly selected photo is moved to the application's storage. The Expo File System component has been added to the application to facilitate this.
Transcript from the "Saving Plant Data" Lesson
[00:00:00]
>> Kadi Kraman: All right, so now we have our image, so we can pick an image from the file system and choose it and it will get displayed here. We also want to save it along with the plant data.
>> Kadi Kraman: So in order to do that, remember that this plant is in our cache, so it's in our device cache.
[00:00:20]
So we can't just store the URI to where it's located because it might not be located there in the future. So what we want to do is we want to make a copy of that file into our device storage. So we know it will be there until our app is deleted.
[00:00:38]
So for this, we're going to use a library called expo-file-system. So this allows you to basically, it's a utility that lets you easily download files, but also move files and read files from your device file system.
>> Kadi Kraman: So let's,
>> Kadi Kraman: Npx expo install expo-file-system,
>> Kadi Kraman: And start the bundle again.
[00:01:21]
>> Kadi Kraman: Okay, so now we would like to pass our plant URI into our addPlant function.
>> Kadi Kraman: So imageUri. So this actually annoys me a little bit, this is a little bit of a caveat. But I tend to follow a rule that if a function has more than two arguments, I convert this into an object.
[00:01:50]
Because otherwise, you need to remember to pass these in the right order. So I would do, yeah, name, I make this into an object. In this case, I'm not going to do it because it's not important to the course, but just FYI, it annoys me and I wouldn't do it in a real app.
[00:02:12]
So in our plantsStore, where we have addPlant, so we have a third argument, which is the imageUri, which is an optional string.
>> Kadi Kraman: And this is another thing, I'm not sure if I'm maybe misusing as a stand, but I find it a little bit annoying that with TypeScript I actually have to type this into places.
[00:02:40]
But sail away. So we have the imageUri, which is an optional string. Okay, so here, where we are adding the plant. So the image you are actually, let me just console.log here what the imageUri is going to be.
>> Kadi Kraman: Okay, so if I do this, and then let's do Test.
[00:03:21]
>> Kadi Kraman: Good thing I've got form validation. All right, so this is what the URI looks like. So it is a file, it's a bigger path for me cuz I'm gonna simulate it and it is a JPEG. But this file could be a PNG or all sorts of other file formats.
[00:03:38]
And I don't want to handle what file format it is. So what I'm doing here is I am just picking the last bit of the file path, which will be the file name, including probably the extension. And I'm going to use this in my copied file path, and then I don't care what the file type is.
[00:03:58]
This is basically what I'm doing here. So we'll do const savedImageUri. So this will be the location where we're going to save this file to. For this, we need to import star as FileSystem from expo-file-system.
>> Kadi Kraman: And we'll do FileSystem.documentDirectory.
>> Kadi Kraman: Right, and then what we're going to add here, I wanted to add a timestamp just to make sure that this is unique.
[00:04:55]
So let's do a new Date.getTime.
>> Kadi Kraman: And then dash.
>> Kadi Kraman: And this is where I'm going to do our magic of getting the last bit of the imageUri. So I'll do imageUri and we'll do a split.
>> Kadi Kraman: We'll split it by the slash, and slice,
>> Kadi Kraman: -1 and take the only item there.
[00:05:41]
So this should work, I haven't tested this on every device, but that is the intent and hopefully it does work. So now, remember this imageUri is optional. So we'll do if there was an imageUri, then we're going to copy it to the saved imageUri location. So we'll do await FileSystem copyAsync.
[00:06:10]
>> Kadi Kraman: And we will copy it from the imageUri,
>> Kadi Kraman: And to the saved imageUri. Now, this is unhappy because it's not an async function, so let's make it async. There we go.
>> Kadi Kraman: And finally, we want to save this imageUri as part of our plant data. So in plants, we're adding a new plant, we'll do imageUri.
[00:06:49]
If there was an imageURI, so this is an optional field. Then this will be the savedImageUri, otherwise, let's default to undefined.
>> Kadi Kraman: And lastly,
>> Kadi Kraman: Where we're rendering these, so this will be on the homepage. So where we have our FlatList, our PlantCard.
>> Kadi Kraman: Yeah, so this gets the whole plant, yeah.
[00:07:22]
So if you go into the PlantCard, so this has the PlantlyImage. And now, recall that this PlantType may include the, need to update this as well. So PlantType, yeah. Yeah, the types on here aren't working as well as expected. So apologies, there is a missing field here. So in this array, so when we're adding a plant, we have an imageUri, so we're adding a new field to our plants.
[00:07:55]
At the top here, we have our PlantType. Let's do the imageUri, which is an optional string.
>> Kadi Kraman: And in our PlantCard, now when we hover over it, this is an optional string and we can pass it into our PlantlyImage. So imageUri = plant.imageUri. So this option, it was still default to our little placeholder image.
[00:08:28]
>> Kadi Kraman: So now when I add any plant, running out of plant names, Sophie The Spider Plant.
>> Kadi Kraman: And well, actually, this is a yellow leaf, this is definitely not a spider plant. But let's save this. There we go. So now when I reload my app, I'm expecting it to still exist here.
[00:08:58]
>> Speaker 2: Notice that addPlant was turned to a promise. Is that a Zustand thing or was that part of the image async for the-
>> Kadi Kraman: It looks like Zustand supports asynchronous functions.
>> Speaker 2: Okay, so you need to change it to-
>> Kadi Kraman: Yeah, I needed to change it to asynchronous, because the process of copying the file over was asynchronous, so in order to await it.
[00:09:27]
>> Speaker 2: Yeah, sure but I was curious in that if you scroll up to the type all the way up to the addPlant.
>> Kadi Kraman: I see.
>> Speaker 2: So you avoid as addPlant is the return value?
>> Kadi Kraman: Okay, so technically, this is a promise, good.
>> Speaker 2: And I was curious if that was because of the async or is that because of the FileSystem saving it?
[00:09:42]
I guess why it was a promise. Looks like it's just returning an object in the function in the set.
>> Speaker 2: It might be beyond the scope of the course, so I was just curious. That was an easy answer to that.
>> Kadi Kraman: Is this in the addPLant?
>> Speaker 2: Yeah.
[00:10:01]
>> Kadi Kraman: I see what you mean, okay.
>> Speaker 2: You're awaiting it, but you're not returning it, you're trying to set, yeah.
>> Kadi Kraman: Okay, I see what you mean. I would say that it is a Zustand thing. So I haven't used Zustand a huge amount-
>> Speaker 2: Sure.
>> Kadi Kraman: So I might be doing something a little bit incorrectly.
[00:10:16]
I wanted to just use the state management library, and I don't mind which one you use. So I'm not claiming to be an expert in Zustand. So some of this stuff that I'm doing might not be totally correct. But I think you don't actually need to return this, I think this is actually a mistake.
[00:10:34]
>> Speaker 2: Cuz if you remove the types, it implicitly tells you that addPlant is a promise. So you got it right, I just didn't know, I was trying to figure out why, interesting.
>> Kadi Kraman: Yeah, actually adding this returns here. I don't think they do anything. Yeah, this returns void, so it returns nothing.
[00:10:50]
So by returning this, I'm returning nothing. So actually, if I hover over it, you can see the type. So it is a function that return void, which is nothing. So this is totally redundant, actually, which was a good spot, but I'm going to-
>> Speaker 2: Yeah.
>> Kadi Kraman: Yeah, they don't make a difference.
[00:11:13]
But this was correct, so it is technically a promise from their usage side.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops