|
| 1 | +# Module Project: Context API - Shopping Cart |
| 2 | + |
| 3 | +In this module you will take your newfound knowledge of `Context API` and refactor a e-commerce store to use `Context API` as well as extend the functionality of the application making it more robust! |
| 4 | + |
| 5 | +## Introduction |
| 6 | + |
| 7 | +Read these instructions carefully. Understand exactly what is expected _before_ starting this project. |
| 8 | + |
| 9 | +### Commits |
| 10 | + |
| 11 | +Commit your code regularly and meaningfully. This helps both you and your team lead in case you ever need to return to old code for any number of reasons. |
| 12 | + |
| 13 | +### Description |
| 14 | + |
| 15 | +In this project you'll take take an almost completed e-commerce store and refactor the application to use the `Context API`. |
| 16 | + |
| 17 | +### Instructions |
| 18 | + |
| 19 | +### Task 1: Project Set up |
| 20 | + |
| 21 | +- [ ] Create a forked copy of this project. |
| 22 | +- [ ] Add your team lead as collaborator on Github. |
| 23 | +- [ ] Clone your OWN version of the repository in your terminal. |
| 24 | +- [ ] CD into the project base directory `cd react-shopping-cart`. |
| 25 | +- [ ] Download project dependencies by running `npm install`. |
| 26 | +- [ ] Start up the app using `npm start`. |
| 27 | +- [ ] Create a new branch: git checkout -b `<firstName-lastName>`. |
| 28 | +- [ ] Implement the project on your newly created `<firstName-lastName>` branch, committing changes regularly. |
| 29 | +- [ ] Push commits: git push origin `<firstName-lastName>`. |
| 30 | + |
| 31 | +### Task 2: MVP |
| 32 | + |
| 33 | +Before you get started, please take a few minutes and get acquainted with this application. Understand what's going on and how it's working. |
| 34 | + |
| 35 | +- If you look in the `App.js` you'll notice there are currently two state properties - `products` to keep track of all available products, and `cart` that will keep track of all the items in our `cart`. |
| 36 | + |
| 37 | +- You'll also notice inside of our `App.js` we have 3 components. A navigation component and two route based components. Each of those components are all being passed either our `cart` state or `product` state as props, when we start to scale our application and add more props our codebase is going to start to become very cumbersome and will make our application hard to work with. |
| 38 | + |
| 39 | +- To combat this from happening we're going to refactor our application to use `Context API`, making it easier and more effiecent to access data across our application. |
| 40 | + |
| 41 | +**Step 1 - Add item functionality** |
| 42 | + |
| 43 | +- In `App.js` there is a function called `addItem`. Finish writing the logic in this function to be able to add the given item to the shopping cart |
| 44 | + |
| 45 | +**STEP 2 - Creating ProductContext** |
| 46 | + |
| 47 | +- In `src`, create a new folder named `contexts`, this folder is going to be used to hold all of `context objects` we create. |
| 48 | + |
| 49 | +- Inside that folder create a new file named `ProductContext.js` |
| 50 | + |
| 51 | +- In this file, import the `createContext` function from the react library and create our `ProductContext`. |
| 52 | + |
| 53 | +**STEP 3 - Providing data with ProductContext** |
| 54 | + |
| 55 | +- Now that we've created our `ProductContext` we can import into our `App.js`. Now we can start providing data across our application! |
| 56 | + |
| 57 | +- Wrap all of your components/routes in `App.js` inside of `ProductContext.Provider` component. |
| 58 | + |
| 59 | +- Next pass a value prop to your `Provider`. |
| 60 | + |
| 61 | +- In the value prop we'll pass in the products state, and an addItem function that will allow us to add books to the cart. |
| 62 | + |
| 63 | +```js |
| 64 | +<ProductContext.Provider value={{ products, addItem }}> |
| 65 | +``` |
| 66 | + |
| 67 | +- Now that we're providing our products state and addItem function we can simplify our products route a bit. |
| 68 | + |
| 69 | +**Before** |
| 70 | + |
| 71 | +```js |
| 72 | +<Route exact path="/"> |
| 73 | + <Products products={products} addItem={addItem} /> |
| 74 | +</Route> |
| 75 | +``` |
| 76 | + |
| 77 | +**After** |
| 78 | + |
| 79 | +```js |
| 80 | +<Route exact path="/"> |
| 81 | + <Products /> |
| 82 | +</Route> |
| 83 | +``` |
| 84 | + |
| 85 | +- After refactoring you'll notice a few errors... Don't worry we'll clean those up shortly! |
| 86 | + |
| 87 | +**STEP 4 - Consuming data with ProductContext** |
| 88 | + |
| 89 | +- Now that our `ProductContext` is now providing data we can finally consume it! To do so let's head over to our `Products` component and import the `useContext` hook as well as our `ProductContext`. |
| 90 | + |
| 91 | +- In the component, call the `useContext` hook and pass in the context object we want to use into it. |
| 92 | + |
| 93 | +- When we do this, `useContext` is going to return value passed by our `ProductContext` Provider `value` prop. In our case we're getting back an object with two properties. A `products` property and a `addItem` property. We can go ahead and destructure those. |
| 94 | + |
| 95 | +```js |
| 96 | +const { products, addItem } = useContext(ProductContext); |
| 97 | +``` |
| 98 | + |
| 99 | +- Now that we have all of the data we need we can refactor our `Products` component from using props. |
| 100 | + |
| 101 | +- To do so we just need to remove every instance of `props`. |
| 102 | + |
| 103 | + - Remove it from the function parameters |
| 104 | + - Remove it from the products map |
| 105 | + - Remove it from addItem prop |
| 106 | + |
| 107 | +- Now our `Products` component is getting it's data solely from `Context API` 😃. |
| 108 | + |
| 109 | +**STEP 5 - Create the CartContext** |
| 110 | + |
| 111 | +- Now that we have refactored our `Products` component to utilize `Context API` let's refactor our `Cart` and `Navigation` Component to use `Context API` as well. |
| 112 | + |
| 113 | +- To start create a new file in our contexts folder named `CartContext.js`, this context is going to be utilized by our `ShoppingCart` and `Navigation` component. |
| 114 | + |
| 115 | +- Inside of our new `CartContext` import `createContext` and create a new context named `CartContext`. |
| 116 | + |
| 117 | +**STEP 6 - Providing data with CartContext** |
| 118 | + |
| 119 | +- Let's go ahead and bring our newly created `CartContext` into our `App.js` and wrap all of our components inside of our `CartContext.Provider`. Make sure our `ProductContext.Provider` is still the root provider. |
| 120 | + |
| 121 | +- Now pass a value prop to our `CartContext.Provider`, this value prop is going to contain our `cart` state. |
| 122 | + |
| 123 | +- Now that we're providing our cart data, we can start to refactor our `Navigation` and `ShoppingCart` components. |
| 124 | + |
| 125 | +- Let's start with our `ShoppingCart` component first. Go ahead and refactor the `ShoppingCart` route to no longer use render props. This will throw us an error, but we'll be able to resolve it quickly. |
| 126 | + |
| 127 | +- While were at it let's go ahead and remove the props from our navigation as well. |
| 128 | + |
| 129 | +**STEP 7 - The final stretch** |
| 130 | + |
| 131 | +- Our cart data is now being provided to us from our `CartContext` time to consume it! |
| 132 | + |
| 133 | +- First, let's head to our `ShoppingCart` component and import the `useContext` hook and our `CartContext`. |
| 134 | + |
| 135 | +- Now in the component, pass `CartContext` to the `useContext` hook and assign it to a variable named cart. |
| 136 | + |
| 137 | +- Inside of our component we now need to remove all instances of props. |
| 138 | + |
| 139 | + - Remove the `props` parameter |
| 140 | + - Remove the `props` portion in our `getCartTotal` function |
| 141 | + - Remove `props` when we're mapping over our cart |
| 142 | + |
| 143 | +- Time to do the same thing for our `Navigation` component. |
| 144 | + - First import the `useContext` hook and our `CartContext` |
| 145 | + - Next, pass our `CartContext` to the `useContext` hook and assign it to a variable named cart. |
| 146 | + - Lastly we need to remove all instances of `props` |
| 147 | + - Remove `props` from our parameters |
| 148 | + - Remove `props` from our cart length |
| 149 | + |
| 150 | +We have now successfully converted our application into using `Context API` 🔥 |
| 151 | + |
| 152 | +**MVP Requirements** |
| 153 | + |
| 154 | +- Create a `ProductContext` and a `CartContext` |
| 155 | +- Use the Provider Component from `ProductContext` and `CartContext` to provide data to child components |
| 156 | +- Consume data using the `useContext` hook from `ProductContext` and `CartContext` |
| 157 | + |
| 158 | +### Task 3: Stretch Problems |
| 159 | + |
| 160 | +Do not attempt stretch problems until MVP has been reached and a final commit has been made. |
| 161 | + |
| 162 | +- Create a `removeItem` function that allows you to remove an item from your cart with a click of a button. This `removeItem` function should be able to be consumed from your `ShoppingCartItem` component. |
| 163 | + Remember each item has an `id` this will help out a lot while creating your removeItem function! |
| 164 | + |
| 165 | +- Persist Cart Items using `localStorage`. (If you try this one, it will be a bit tricky to get our items to populate the shopping cart on a refresh. You'll have to think about where the data actually lives, and how you can get data there from localStorage when the app is being mounted after a refresh. Good luck!) |
| 166 | + |
| 167 | +## Submission Format |
| 168 | +* [ ] Submit a Pull-Request to merge `<firstName-lastName>` Branch into `main` (student's Repo). **Please don't merge your own pull request** |
0 commit comments