# Client Server Communication part 2 ![Client Server Flow Diagram](https://res.cloudinary.com/dnocv6uwb/image/upload/v1626895908/flow-diagram_prnjyq.png) [GitHub Source Code](https://github.com/learn-co-students/central-051721/tree/main/phase-4/solutions/03-client-server-communication-part-2) ## Feature: ### What's my client side route? ### Which component does it render? ### Where should the useEffect/event handler send a request to? ### What controller#action does the server side route point to? ### What data is retrieved from/created in/deleted from the model layer? ### What should the server JSON response look like? ### After we parse response as JSON on the client side, what's the next step? ## Task 1 - Adding a Buy button Let's review how to handle POST requests to create by adding a buy option to our items. In our case, buying an item will create an order. - Add a Buy Button to the Item Card (that creates an order for that item) - Add an Order show route (client side) that displays the `OrderCard` component - fetches order data from the API - Displays order ### What's my client side route? We start at `'/'` After we click we end up at `'/orders/:id'` ### Which component does it render? `/` => `ItemContainer` `/order/:id` => `OrderCard` ### Where should the useEffect/event handler send a request to? Event Handler (onClick) for the buy button sends request to: `POST '/orders'` What's the body? Use some info from props to put in body of request. How do we know what should be in the body of the request? ### What controller#action does the server side route point to? `OrdersController#create` ### What data is retrieved from/created in/deleted from the model layer? ```rb def order_params params.require(:order).permit(:user_id, :item_id) end ``` ```js { order: { user_id: 2, item_id: 1 } } ``` ### What should the server JSON response look like? the newly created `Order` ### After we parse response as JSON on the client side, what's the next step? client side redirect to `/orders/${apiOrder.id}` We'll display order using the OrderCard component Unhandled Rejection (TypeError): Cannot read property 'item_name' of undefined ```js return ( <> {order?<div key={order.id}>Item:{order.item.item_name} User:{order.user.user_name}</div>:null} </> ) ``` You have a line number, and you're looking for the place on that line where item_name appears. This error is telling you that the expression before item_name returns undefined. ### Relevant Code Changes ```js // src/App.js // Import OrderCard component // Add Route pointing to OrderCard component <Navbar /> <Switch> <Route path="/items/new"> <ItemForm items={items} setItems={setItems} /> </Route> <Route exact path="/"> <ItemContainer items={items} setItems={setItems} /> </Route> <Route exact path="/orders/:id"> <OrderCard /> </Route> </Switch> ``` ```js // src/OrderCard.js import { useParams } from "react-router-dom"; import React, { useState, useEffect } from 'react' function OrderCard() { const [order, setOrder] = useState(null); const id = useParams().id useEffect(() => { async function fetchOrder(){ let res = await fetch(`http://localhost:3001/orders/${id}`) let json = await res.json() setOrder(json) } fetchOrder() },[]); return ( <> {order?<div key={order.id}>Item:{order.item.item_name} User:{order.user.user_name}</div>:null} </> ) } export default OrderCard; ``` ```js // src/ItemCard.js import { Card, Image } from './styled'; import { useHistory } from 'react-router-dom' function ItemCard({ item }) { const history = useHistory(); async function handleClick(e) { const res = await fetch(`http://localhost:3001/orders`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ order: { user_id: 2, item_id: item.id } }) }) const json = await res.json() history.push(`/orders/${json.id}`) } return ( <Card> <Image src={item.image_url} /> <h2>{item.item_name}</h2> <h2>{item.price}</h2> <p>{item.description}</p> <p> <button onClick={handleClick }>Buy</button> </p> </Card> ); } export default ItemCard; ``` ```js // src/ItemContainer.js ``` ```js // src/ItemForm.js ``` ```js // src/Navbar.js ``` ## Task 2 - Adding an edit Item feature - Add an Item edit route (client side) that - fetches item data from the API - loads it into the controlled form - handles submission by updating the Item on the backend - redirects to the items index route (client side) where we should see the updated item info ### What's my client side route? `/items/:id/edit` => `EditItemForm` ### Which component does it render? ### Where should the useEffect/event handler send a request to? ### What controller#action does the server side route point to? ### What data is retrieved from/created in/deleted from the model layer? ### What should the server JSON response look like? ### After we parse response as JSON on the client side, what's the next step? ### Relevant code changes ```js // src/App.js ``` ```js // src/OrderCard.js ``` ```js // src/ItemCard.js ``` ```js // src/ItemContainer.js ``` ```js // src/ItemForm.js ``` ```js // src/Navbar.js ``` ## Task 3 In breakouts - Adding a Delete Button to Item Card - Add a Delete Item button to the Item Card - When clicked the button should send a request to the API to delete the Item - when we get a successful response we should remove the Item from the items index view - should allow us to delete items even if they have associated orders. ### What's my client side route? `'/'` is active and we won't redirect ### Which component does it render? ItemContainer ### Where should the useEffect/event handler send a request to? event handler should send request to: DELETE /items/:id ### What controller#action does the server side route point to? items#destroy ### What data is retrieved from/created in/deleted from the model layer? destroy the item in the database ### What should the server JSON response look like? deleted item in JSON format ### After we parse response as JSON on the client side, what's the next step? update our state in ItemContainer to remove the card for the deleted item ## Final Code ```js // src/App.js ``` ```js // src/OrderCard.js ``` ```js // src/ItemCard.js ``` ```js // src/ItemContainer.js ``` ```js // src/ItemForm.js ``` ```js // src/Navbar.js ```