This course has been updated! We now recommend you take the Build Progressive Web Apps (PWAs) from Scratch course.

Check out a free preview of the full Progressive Web Applications and Offline course:
The "Challenges 4 & 5: Solutions" Lesson is part of the full, Progressive Web Applications and Offline course featured in this preview video. Here's what you'd learn in this lesson:

Steve walks through the solution to Challenges 4 and 5 with Steve's help.

Get Unlimited Access Now

Transcript from the "Challenges 4 & 5: Solutions" Lesson

>> Steve Kinney: All right, so we have two missions. Mission one, put stuff in the cart. And by put stuff in the cart, we mean don't lie about it, right? Actually tell the server to put it in the cart. Rather than going, yeah, it's totally in the cart. Because if we go right now and we check it out, we can put some stuff in the cart, put in some of that, I'll put some of these other things in here, some almond milk, some feta cheese.

[00:00:24] I'm gonna go wild. And then I'm gonna refresh the page. [SOUND] There's nothing in the cart because I didn't actually do it. And so now our job is to tell the server that we did it as well. So one of our goals was to take this lie, this false promise.

[00:00:46] I mean they technically say it's a promise but it is like a disingenuous promise. And replace it with a fetch call that will return a promise and will return that instead, which is did it work or did it not work? Here we're saying, it worked. We didn't do anything but that nothing that we did, it worked.

[00:01:02] Right, here we're gonna say, let's see, I'll try it out. Here's a promise, here's an IOU. It'll resolve when we hear back from the server on whether or not it actually worked. All right, so I definitely know that this is bogus, cool. So what I'm gonna do is I'll just comment it out for now cuz I'm very cautious and will never actually delete code.

[00:01:28] I'm all about deleting code, I'm a liar. So return is some kind of fetch, right? We know that we wanna fetch some kind of data. Scrolling around, I can see that Mike was nice enough for bringing us an API endpoint. Which is, at this point, it reads like basically it's localhost 3100.

[00:01:49] But I'll use that for now. I could also hard code in localhost 3100. We could actually see it in the restore cart. We can see a fetch that was hidden in there as a little trick for anyone looking around. There was a hidden fetch in there for you.

[00:02:02] So we actually start with that, right, cuz that looks pretty similar. This is good, I like this. I want this, I'm taking this. What's the problem with taking this? Anyone have a lucky guess? Anyone want to ruin my day and tell me what's gonna go wrong for me?

>> Speaker 2: Your HTTP verb is wrong.
>> Steve Kinney: Yeah, by default, fetch will do its synonym get, right? But we don't want to get. Does anyone know what we wanna do?
>> Speaker 2: Put.
>> Steve Kinney: Put, okay, so it's a good step in the right direction, but it is not going to do the trick for me.

[00:02:41] But let's save it, and let's be adventurous and see what happens
>> Steve Kinney: We could see that it completed. For instance, if I really wanted to, I could say then(data,
>> Steve Kinney: Whoa, that was fun, and console.log(data), right? Clearly, this is not going to be what I think it is.

[00:03:06] This is going to be all the stuff in the cart, which is effectively nothing, because we don't have the ability to put stuff in the cart yet.
>> Steve Kinney: All right, so put stuff in. You can see I got that empty array in there. Okay, great, not so great, but we'll go with it.

[00:03:27] All right, but we do have the basis of what we need in this case. Anyone have a lucky guess on how we might take this fetch? Right, cuz I gave it a URL, what more could it possibly want? Lucky guesses?
>> Speaker 2: An object.
>> Steve Kinney: An object of options.

>> Steve Kinney: All right, and for my own neuroses, there we go, cool. I don't actually even like that, but we'll deal with it. All right, so how would we send something? We're passing some options, what would it make sense to, if we wanna set the method to a put, what might we try?

>> Speaker 2: Setting a method property to PUT.
>> Steve Kinney: I like it. I like his thinking. [LAUGH] We can set a method to PUT. That seems good. I like that.
>> Speaker 2: Need some data.
>> Steve Kinney: Yeah, so what are we putting is, I think, the next obvious question, right? And the reason that I didn't comment this out before is, clearly, this cart store has some idea of items, right?

[00:04:35] Seems like we should send those to the server. I like this train of thought. All right, how might we do that? So requests, if I remember, like-
>> Speaker 2: Body?
>> Steve Kinney: Body, they have a head and they have a body, right? Seems like this data might be the what, the head, right?

[00:04:57] The body, it's too late in the afternoon for jokes. The body and what should the body be?
>> Speaker 2: The items.
>> Steve Kinney: The set items, this may or may not work, we'll find out.
>> Steve Kinney: That's strange.
>> Speaker 2: It needs a content type header.
>> Steve Kinney: Interesting, how am I gonna try to do that?

>> Speaker 2: Headers.
>> Steve Kinney: Headers, okay that seems good. So we'll take some headers. It doesn't really matter the order here, but again, all right, there are lots of different headers. It seems like I need, again, to configure this request. What kind of header do I want again?
>> Speaker 2: Content type.

>> Steve Kinney: Content type that seems good. What kind of content is this?
>> Speaker 2: Application JSON.
>> Steve Kinney: You know the answers already, don't you? [INAUDIBLE] All right, cool, put a comma in there. All right, now what do we have?
>> Steve Kinney: All right, seem to be rejected cannot read property map of undefined, strange.

>> Speaker 2: [CROSSTALK]
>> Steve Kinney: Yep, because it doesn't know how to deal with this.
>> Steve Kinney: All right, I'll try it again.
>> Steve Kinney: Nope.
>> Speaker 2: Sorry, if I'm cheating here. So the API example had a top level key of data.
>> Steve Kinney: Uh-huh.
>> Steve Kinney: In the meantime. All right, so if we go back and we take a look at our API playground, right, we can see that it's expecting stuff to be in this data.

[00:07:08] Right, and we didn't do it. We just sent it in an array. We're like, here, and so likely what the API is doing is it's saying, cool I got something really excited about this. Let me go get the data key out of it and it's an array. So you got back undefined.

[00:07:20] And let's map all of them now. And we called map on undefined, and then sadness ensues, right?
>> Steve Kinney: Cool.
>> Steve Kinney: So what do we need to do? Looks like this is the culprit. It's expecting an object with a data key, so.
>> Speaker 2: Make an object with a data key?

>> Steve Kinney: Make an object with a data key give the server what it wants. That's our job as front end developers. All right, I'm excited now. I think this is really where things come together for us. Hey, hey, stuff went in there, things were good, fetch complete. All right, moment of truth I refresh the page.

[00:08:08] We could actually put stuff in the cart in our shopping cart app. I will tell you that this back end is fake, and you can't actually order groceries so don't get too excited. But if this was a real app, we could totally put real stuff into our fake app now.

[00:08:25] That said, we got something in the cart. I'm excited. Let's go ahead checkout. Yes, I'm sure. Boom, uncaught, cart store to checkout not yet implemented. Somebody went home early for the weekend? So let's check it out. Let's look for, nope.
>> Steve Kinney: doCheck out, a-ha, well that makes sense.

[00:08:47] That explains the error message. doCheckout immediately just throws an error. All right, so in this case, it's kind of like we're gonna repeat a lot of the same logic here. What we wanna do is does anyone remember the API for creating an order?
>> Speaker 2: API/order.
>> Steve Kinney: API/order, what kinda method do I need?

>> Speaker 2: POST.
>> Steve Kinney: It's a POST, right, cuz we're gonna create one. Cool, so what we'll do is, when this happens, we'll return a new promise, return new fetch, seems good. Look at that fancy API endpoint that Mike made us. So we've got API endpoint, and we know that that's api/order.

[00:09:33] All right, again, just firing this off is gonna make what kinda request?
>> Speaker 2: Get.
>> Steve Kinney: A get, that's not what we want. We want a method of?
>> Speaker 2: Host.
>> Steve Kinney: Host, cool, all right, now again, a little bit of the same, we're gonna send JSON. And we know it's gotta be in the body, so there's not like a lot of incognita here.

[00:09:59] So we'll say, 'content-type'.
>> Speaker 2: Headers object.
>> Steve Kinney: Good catch.
>> Steve Kinney: Got background music for this?
>> Steve Kinney: All right, and it's 'application/json' again. Nothing's really changed in this part of the app.
>> Steve Kinney: All right, the other thing we've given it the right headers, what else do we need to give it?

>> Speaker 2: The stuff.
>> Steve Kinney: The stuff give it the stuff. That's the stuff key right. [LAUGH] We give it the body, and again, that is gonna be very similar to what we had before. Except, this time we know that's expecting a data keyword. I'll pass that in. Now when stuff happens, there's a little bit more.

[00:10:49] Remember, if we go back to the test that we were given, there's a little bit more to it. It says after the API call is completed, call _restoreCart to update the client's view of any changes that might have happened as a result of the order, right? And then theoretically, we're gonna get back these new items that we can set to be the new contents of the cart, right?

[00:11:12] So we're still gonna get back some more stuff. So our job is done. We've created the order. There's more information coming back at us now.
>> Steve Kinney: Luckily for us, really, the hard work has already been done for us.
>> Steve Kinney: Take that. Take that with me. Thanks, Mike. [LAUGH] Cool.

>> Steve Kinney: Right, so what's happening here? Okay, if we have successfully, in a fake server running on localhost, it's pretty hard to have a network error, unless we turn the app offline. Wonder if that's gonna happen at some point today. But right now we can assume we're gonna be successful.

[00:12:00] And we'll go ahead and when that happens, when we hear back from the network, either way, it could have been a 404 or whatever. In this case, we're kind of naive. In a real robust application, you might handle permission denied you didn't have access to that cart. We're keeping it simple cuz it's not the total focus of today.

[00:12:19] We're gonna call this a store cart method, which we'll take a look at a second. That returns a promise, right, cuz that's gotta do some extra stuff. That's gonna have all of the new items ready for us. And at that point, we set that to be the items in the store, and we tell React, hey I've got new items.

[00:12:36] Change the UI to reflect that, and we can see that when that happens, I can hit Yes.
>> Steve Kinney: Not if you don't save the file you can't do anything.
>> Steve Kinney: Checkout, hit Yes. And we see my cart is, at this point, empty.
>> Speaker 2: Let's click on the little top left icon when you're done here, the little grocery awning.

>> Speaker 2: Yep.
>> Steve Kinney: Look at that, we've got a pending order, right? So our server works, we have done the task. So that means that in a workshop on progressive web apps, again, web apps that feel like native apps. Native apps, which a lot of times work offline. We have totally implemented the ability to send network requests.

[00:13:29] Seem like there is more to this puzzle. Seems like we're not out of the woods yet on this. We've managed to learn a new API for sending network requests, right? And this API is foundational to the next piece, but it is, again, we've been building up slowly. We understand that this idea of work doesn't work on another thread.

[00:13:48] We understand this idea of using Fetch to do low level network requests. Right, we understand this idea of a Promise API. We've been building up and building up and building up, right? And now it's the point we can actually get to what I like to think of as the crown jewel of progressive web applications.