‫Let's start this lecture
‫by taking a look at our project requirements
‫to see what we actually already implemented.
‫So, up until this point, actually all we did
‫was to load the menu from the API.
‫So, that's really the only thing here.
‫But since we are now loading data from API,
‫let's also load individual orders.
‫So, basically so that we can implement
‫this other feature here where a user can
‫look up their order based on the ID of that order.
‫So, we cannot create orders yet,
‫but we can already use some dummy IDs
‫to look up orders that had been placed before.
‫And so, let's now implement that functionality.
‫So, basically, now we are going to work on this
‫route right here and on this order page.
‫So, actually, right now, if we go to /order
‫and then slash something here, we will actually
‫already get one dummy order right here.
‫So, if we take a look at our order component here,
‫so, we see that we then have
‫this fake order here, basically.
‫So, this order object right here is what
‫right now is being displayed over here.
‫But, of course, what we want to do next
‫is to make this dynamic.
‫So, we want to read the order ID here
‫from the URL and then display all the data
‫regarding this exact order here on our page.
‫And so, that's what we will implement now.
‫So, the first thing that we need to do is
‫to implement a way in which we can actually
‫search for the order, so in which we can
‫input the order ID into our application.
‫So, basically, we want a search field
‫right here in the header so that we can
‫always access the search functionality from everywhere.
‫So, let's then create a new component.
‫And, since this component is gonna be related
‫to searching a new order, it is,
‫of course, part here of the order feature.
‫And so, let's create that component
‫right here in this folder.
‫So, let's say, "SearchOrder.JSX,"
‫and then, here, let's just return an input.
‫So, the placeholder should be "Search order #".
‫Then, let's make this actually a controlled element.
‫So, that means that we need some state now.
‫So, let's call it query, and setQuery,
‫useState with an empty string.
‫So, this is something we have done many, many times,
‫so we already know really well how this works,
‫so this requires no explanation anymore.
‫So, here when we change then the text
‫we will update the query with e.target.value.
‫All right.
‫And now, in order to actually automatically
‫submit this input field, let's wrap it into a form.
‫So, that's a nice trick with which
‫we can basically automatically submit this input value
‫here simply by hitting the enter key.
‫So, let's then used onSubmit here
‫and create, as always, a handleSubmit function.
‫So, this then needs to receive the event
‫so that we can do event.preventDefault
‫because otherwise this will then create
‫a new navigation which we do not want
‫in a single page application like this.
‫All right, now we are not done yet,
‫but I still want to already include this here.
‫So, SearchOrder, and here it is.
‫All right, so what do we want to happen here
‫whenever we type something and then hit enter?
‫Well, we will want to move to this page right here.
‫So /order/, and then whatever we type here,
‫because here we will have the ID.
‫Now, first of all, if there is no query, then just return.
‫But otherwise, what we want to do
‫is to then navigate to that page.
‫So, for that, we again need the navigate function.
‫So, just like we learned before in a previous project.
‫So, for that, we use the useNavigate hook
‫and then here we can call navigate to
‫/order/ and then the query.
‫And then, finally, let's set the query back to empty.
‫And this should be all we need.
‫So, let's come back here, let's try something.
‫Then, I will hit the return or
‫the enter key... and beautiful.
‫So, here we have now order/ this ID,
‫but of course, this here is still the dummy data.
‫So, next up what we need to do is to then
‫actually fetch the data from the API.
‫So, using this getOrder function that we already have
‫which will receive exactly that ID right there.
‫Okay, so this one is finished.
‫And so, let's now work here on the order.
‫And so, the way we will do this is exactly
‫the same way as we did with the menu.
‫So, first of all, we create our loader function.
‫So, we will do that again right here inside the component.
‫Then, we will connect the loader function
‫with the route definition right here,
‫and then, in the page component itself,
‫so inside the order, we will get that data.
‫All right. And we could even define
‫the loader function, of course, right here.
‫So you wouldn't have to place it inside this file,
‫but it's a bit of a convention to do so.
‫So, let's do export the async function called loader.
‫And then, here, what we want to do is to get the order.
‫So we do await getOrder, but now remember
‫that this needs to receive the ID.
‫So, how do we get the ID from the
‫URL right into this function?
‫Well, we previously used the useParams hook, right?
‫So something like this. However, since this is a hook
‫it only works inside components.
‫It doesn't work in regular functions.
‫So, let's remove that, and also from here,
‫since we don't need that.
‫But, luckily for us, React Router has, of course,
‫thought of the situation, and therefore it passes
‫in some data into the loader function as it calls it,
‫and one of the properties of the object that
‫the loader function receives is exactly the params.
‫So, we de-structure that object here
‫and get out the params.
‫And so, here, we then get params.orderId
‫and it is called orderId because that is
‫exactly the name that we gave it here.
‫So, this is the name of our param, right?
‫So, getOrder... apparently we didn't import that.
‫And now, all we need to do is to
‫really return something from the loader function.
‫And then, let's connect the two.
‫So, we use loader, but first of all,
‫we need to, of course, import that here.
‫So, right here, loader as orderLoader.
‫So, that's a bit of a funny name.
‫But anyway, let's now connect that here
‫and immediately, we get some error here.
‫So, couldn't find order with this ID
‫which is already nice, I guess.
‫So, something is already working, but of course,
‫we, again, want to see this error inside the actual layout.
‫So, let's again grab this error element here
‫and paste that right here.
‫And so, this is a lot nicer.
‫Now, let's come here to this order
‫because here, actually, I have a test ID.
‫So, let's grab that and paste that here.
‫Or, of course, we could also write it there.
‫That would be the exact same thing.
‫And now, we do not get an error anymore,
‫meaning that something worked.
‫But still, we have this fake order right here
‫because that's still the one that we are using.
‫So, this order object that we had right there.
‫And so, now, as a third step,
‫we need to get the data from the loader.
‫And so, just like before, let's actually do this here.
‫So, let's do useLoaderData.
‫And so, this is now the new order,
‫so we can delete this one here.
‫All right. But what matters is that now
‫we are actually getting this data from the API.
‫So, this is now the actual fetched data,
‫and we can confirm this if we use another ID here.
‫So, let's use CQE92U, then hit enter.
‫And now, indeed, the data has changed here.
‫And maybe you noticed that actually we also had
‫our loading indicator automatically working up here, right?
‫So, let's try that again.
‫So, let's copy again this one, and then
‫you will notice that we automatically
‫get the loading indicator right up there.
‫And then, once that is done, the data here will change.
‫So, let's try that.
‫So, sometimes, this API will take some time
‫to fetch the data. That's completely normal.
‫But now, here it is, and it is, indeed,
‫really nice that we automatically
‫get that loading indicator right there,
‫which is because of the reason that I mentioned earlier,
‫which is the fact that this navigation state here
‫really is universal for the entire application.
‫So, that's the whole reason why we placed this
‫loading indicator in the app layout in the first place,
‫because this will then render our loader
‫each time that somewhere in the app something is loading.