Updating the quantity of a product is an essential feature for a great checkout experience. In this lesson, we will create a feature to update the quantity of each product in our cart.
We'll create a new component with a form input to increment the number of items and a button to submit that form. Additonally, we will create an updated item function in the useCart
hook that adds the ability to update the quantity of a product in the shopping cart by ID and trigger an update whenever the quantity form on the cart table is submitted.
Lecturer: [0:00] We're going to start off with our Space Jelly Shop Next.js App. We have this cart page where if somebody adds a product to their cart, we can see it represented in this table. The only issue is currently our customers don't have a way to update that cart.
[0:10] We need to give them a way to update the quantity and even set it to if they don't want an item anymore. As a solution, instead of just showing a number for our quantity, we can use an input so that somebody can update it.
[0:21] Inside our code, we're currently creating our table data by mapping through our cart items. Inside of our table component, we can see that as this table is mapping through the data, it's rendering out the cell as a child. That means, as we're mapping through our cart items, we can set our quantity to a React component.
[0:36] To test this out, I'm going to start off by creating a constant called quantity, where I'm going to set that equal to a new component. Inside of my component, I'm simply going to return a paragraph tag, where I'm just going to say quantity.
[0:47] Inside of the object that we're returning on that map, we want to set the quantity property to a quantity component. If we reload the page, we can already see our quantity text. If we want to make this something somebody can update, we want to make this a form that includes an input and a button that somebody can trigger the update.
[1:03] I'm going to replace this with a new form component. Inside of my form, I'm going to create a new input with a type of number, a name of quantity, a min of because we don't want somebody to go negative. For a default value, we want to set it equal to the item.quantity.
[1:19] If we reload the page, we can already see our input with our current quantity. We can increment that and change it, but it's currently not going to do anything. Additionally, we want to first add a button component, where we can just add the text update.
[1:29] When someone clicks this button, it's going to submit this form. We're going to intercept that by adding an onSubmitHandler onto our form, where we're going to create a new function called handleOnSubmit. Inside our quantity component, we're going to define that new function where we're going to grab the first argument event, and we're going to tell it to prevent the default functionality.
[1:47] As usual, to test that this is working, we can console.log out simply the word Submit. Inside of our browser, if we hit this Update button, we can see that it's firing Submit. Whenever somebody submits this form, we want to update our current state to the current quantity. In order to update that quantity, we need to know what the value is inside of this input.
[2:05] First, we're going to destructure our currentTarget from our event. This currentTarget is going to be our form. When we submit a form and we grab our form as a currentTarget, we have the property elements available to us where that property elements is going to be a list of nodes. Just to be clear, it's a list of nodes, not an array.
[2:23] The first thing to use those elements, we can create a new constant called inputs, where we can use the array from method, and we can pass in our currentTarget elements where our inputs constant is now going to be an array of nodes. We want to find the quantity input.
[2:38] We're going to create a new constant called quantity. For its value, we're going to run the find method, where our argument is going to be an input, but for our function, we want our input name to equal quantity.
[2:49] Additionally, since we ultimately want to find the value of it for our quantity, we can use the optional chaining operator where we look for the value of that input. That means if we find our quantity input in the array of inputs, we're going to grab its value. Otherwise, if it doesn't find it and this is undefined, because we use this optional chain operator, it's going to stay as undefined.
[3:10] Let's test this out by taking our quantity constant and including that in our console.log. We're back in our browser. We can see that if we hit the Update function, we see three. If we increment that, we now see four.
[3:20] Finally, we want to update our cartState with that new value. Inside of our useCart hook, we have an addToCart function, but we don't have an ability to simply update that value. We're going to create a new function called updateItem. To start, we're going to copy the code inside of our addToCart function and paste that in our updateItem function.
[3:38] Similar to the addToCart function, we want to first destructure our ID, but we also want to destructure our quantity value. Now instead of trying to increment the quantity value, we're going to set that quantity equal to exactly the quantity that we pass in as an argument. We can also get rid of this else clause because we don't want this running if we don't actually find a product.
[3:57] Now with our function, similar to addToCart, we can copy this function and we can return it in our cartState object. Back on our cart page, we're going to destructure that updateItem from our useCart hook.
[4:06] After we find that quantity, we're going to run that updateItem function where we're going to pass in an object. We're going to pass in the ID as item.ID. We're going to set the quantity property, but we're not going to simply just pass in as is, we're going to first check if it exists. Then we'll pass it as an integer so that when we're setting that value, we're setting it as a number.
[4:28] Now if we go back to our page, we can see our initial values, but now if we try to increment the value and hit Update, we can see that not only did our item total update, but if we reload the page, we can see that it still stays as four. When we make those changes, when we go to Stripe, those changes will still be reflected.
[4:44] In review, we had a cart page that showed each of our items in our cart, but we didn't have a way to update it. To provide our customers a way to update it, we added a form with an input and an update button where they can now change the value and update it in their cart.
[4:57] Inside our code, we were able to do that by creating a quantity component that used a new updateItem function that we added to our useCart hook that we passed in as a property inside of our table data. Whenever we ran that updateItem function, if we can find the item, we're going to update it to the quantity that we pass in.
[5:12] After making that available in our useCart hook, we were able to fire it whenever somebody submitted the form so that when somebody updated the quantity of their items, they were able to go to Stripe and check out with that new quantity and cost.
How to handle the successful payment, after payment is made, the stripe redirects to the application with session_id then what to do next, please cover this also
You can use that session ID and the Stripe API to look up the order and display details on the "receipt" or order confirmation page. You additionally would likely want to clear the cart state as at that point, the items would have been purchased.
If a cart item is updated to '0', how do you remove that row from the table dynamically?
This is what I did in the useCart.js file:
// Update number of items in cart function updateItem({id, quantity}) { updateCart((prev) => { let cart = {...prev}
if (cart.products[id]) {
cart.products[id].quantity = quantity
} else {
cart.products[id] = {
id,
quantity: 1,
}
}
if (cart.products[id].quantity === 0) {
delete cart.products[id]
}
return cart
})
}
How to handle the successful payment, after payment is made, the stripe redirects to the application with session_id then what to do next, please cover this also