Created
February 2, 2025 13:37
-
-
Save helabenkhalfallah/3a773625ef0693d575460ba6c4058157 to your computer and use it in GitHub Desktop.
Refactoring Example 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect } from "react"; | |
export default function OrderDashboardBadWay({ userId }) { | |
const [orders, setOrders] = useState([]); | |
const [loading, setLoading] = useState(true); | |
const [error, setError] = useState(null); | |
const [selectedOrder, setSelectedOrder] = useState(null); | |
const [formattedOrders, setFormattedOrders] = useState([]); | |
useEffect(() => { | |
async function fetchOrders() { | |
try { | |
const response = await fetch(`/api/orders/${userId}`); | |
if (!response.ok) throw new Error("Failed to fetch orders"); | |
const data = await response.json(); | |
setOrders(data); | |
} catch (err) { | |
setError(err.message); | |
} finally { | |
setLoading(false); | |
} | |
} | |
fetchOrders(); | |
}, [userId]); | |
useEffect(() => { | |
if (orders.length > 0) { | |
const formatted = orders.map((order) => ({ | |
...order, | |
dateFormatted: new Date(order.date).toLocaleDateString(), | |
totalFormatted: `${order.total.toFixed(2)} USD`, | |
})); | |
setFormattedOrders(formatted); | |
} | |
}, [orders]); | |
const handleOrderClick = (order) => { | |
if (selectedOrder && selectedOrder.id === order.id) { | |
setSelectedOrder(null); | |
} else { | |
setSelectedOrder(order); | |
} | |
}; | |
if (loading) return <p>Loading orders...</p>; | |
if (error) return <p>Error: {error}</p>; | |
return ( | |
<div> | |
<h1>Order Dashboard</h1> | |
<ul> | |
{formattedOrders.map((order) => ( | |
<li key={order.id} onClick={() => handleOrderClick(order)}> | |
<p>Order #{order.id}</p> | |
<p>Date: {order.dateFormatted}</p> | |
<p>Total: {order.totalFormatted}</p> | |
{selectedOrder && selectedOrder.id === order.id && ( | |
<div> | |
<p>Items:</p> | |
<ul> | |
{order.items.map((item) => ( | |
<li key={item.id}>{item.name} - {item.price} USD</li> | |
))} | |
</ul> | |
</div> | |
)} | |
</li> | |
))} | |
</ul> | |
</div> | |
); | |
} | |
// 1️⃣ Extract API Fetching Logic into useFetchOrders.js | |
import { useState, useEffect } from "react"; | |
export function useFetchOrders(userId) { | |
const [orders, setOrders] = useState([]); | |
const [loading, setLoading] = useState(true); | |
const [error, setError] = useState(null); | |
useEffect(() => { | |
async function fetchOrders() { | |
try { | |
const response = await fetch(`/api/orders/${userId}`); | |
if (!response.ok) throw new Error("Failed to fetch orders"); | |
const data = await response.json(); | |
setOrders(data); | |
} catch (err) { | |
setError(err.message); | |
} finally { | |
setLoading(false); | |
} | |
} | |
fetchOrders(); | |
}, [userId]); | |
return { orders, loading, error }; | |
} | |
// 2️⃣ Extract Formatting Logic into formatOrders.js | |
export function formatOrders(orders) { | |
return orders.map((order) => ({ | |
...order, | |
dateFormatted: new Date(order.date).toLocaleDateString(), | |
totalFormatted: `${order.total.toFixed(2)} USD`, | |
})); | |
} | |
// 3️⃣ Create a Reusable OrderList Component | |
import React from "react"; | |
export default function OrderList({ orders, onOrderClick, selectedOrder }) { | |
return ( | |
<ul> | |
{orders.map((order) => ( | |
<li key={order.id} onClick={() => onOrderClick(order)}> | |
<p>Order #{order.id}</p> | |
<p>Date: {order.dateFormatted}</p> | |
<p>Total: {order.totalFormatted}</p> | |
{selectedOrder && selectedOrder.id === order.id && <OrderDetails order={order} />} | |
</li> | |
))} | |
</ul> | |
); | |
} | |
// 4️⃣ Create a Separate OrderDetails Component | |
import React from "react"; | |
export default function OrderDetails({ order }) { | |
return ( | |
<div> | |
<p>Items:</p> | |
<ul> | |
{order.items.map((item) => ( | |
<li key={item.id}> | |
{item.name} - {item.price} USD | |
</li> | |
))} | |
</ul> | |
</div> | |
); | |
} | |
// 5️⃣ Final Refactored OrderDashboard.jsx Component | |
import React, { useState } from "react"; | |
import { useFetchOrders } from "./useFetchOrders"; | |
import { formatOrders } from "./formatOrders"; | |
import OrderList from "./OrderList"; | |
export default function OrderDashboard({ userId }) { | |
const { orders, loading, error } = useFetchOrders(userId); | |
const formattedOrders = formatOrders(orders); | |
const [selectedOrder, setSelectedOrder] = useState(null); | |
const handleOrderClick = (order) => { | |
setSelectedOrder((prev) => (prev?.id === order.id ? null : order)); | |
}; | |
if (loading) return <p>Loading orders...</p>; | |
if (error) return <p>Error: {error}</p>; | |
return ( | |
<div> | |
<h1>Order Dashboard</h1> | |
<OrderList orders={formattedOrders} onOrderClick={handleOrderClick} selectedOrder={selectedOrder} /> | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment