Skip to content

Commit 519e2cf

Browse files
committed
Optimistic updates
1 parent 7b3dace commit 519e2cf

File tree

2 files changed

+54
-26
lines changed

2 files changed

+54
-26
lines changed
Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { removeProduct } from "@/actions/products";
21
import { getProducts } from "@/prisma-db";
3-
import Link from "next/link";
2+
import { ProductDetail } from "./product-detail";
43

54
export type Product = {
65
id: number;
@@ -11,28 +10,6 @@ export type Product = {
1110

1211
export default async function ProductsPrismaDBPage() {
1312
const products: Product[] = await getProducts();
14-
return (
15-
<ul className="space-y-4 p-4">
16-
{products.map((product) => (
17-
<li
18-
key={product.id}
19-
className="p-4 bg-white shadow-md rounded-lg text-gray-700"
20-
>
21-
<h2 className="text-xl font-semibold">
22-
<Link href={`/products-db/${product.id}`}>{product.title}</Link>
23-
</h2>
24-
<p>{product.description}</p>
25-
<p className="text-lg font-medium">${product.price}</p>
26-
<form action={removeProduct.bind(null, product.id)}>
27-
<button
28-
type="submit"
29-
className="px-4 py-2 mt-4 text-white bg-red-500 rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-600"
30-
>
31-
Delete
32-
</button>
33-
</form>
34-
</li>
35-
))}
36-
</ul>
37-
);
13+
14+
return <ProductDetail products={products} />;
3815
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"use client";
2+
3+
import { useOptimistic } from "react";
4+
import { removeProduct } from "@/actions/products";
5+
import Link from "next/link";
6+
7+
export type Product = {
8+
id: number;
9+
title: string;
10+
price: number;
11+
description: string | null;
12+
};
13+
14+
export const ProductDetail = ({ products }: { products: Product[] }) => {
15+
const [optimisticProducts, setOptimisticProducts] = useOptimistic(
16+
products,
17+
(currentProducts, productId) => {
18+
return currentProducts.filter((product) => product.id !== productId);
19+
}
20+
);
21+
22+
const removeProductById = async (productId: number) => {
23+
setOptimisticProducts(productId);
24+
await removeProduct(productId);
25+
};
26+
27+
return (
28+
<ul className="space-y-4 p-4">
29+
{optimisticProducts.map((product) => (
30+
<li
31+
key={product.id}
32+
className="p-4 bg-white shadow-md rounded-lg text-gray-700"
33+
>
34+
<h2 className="text-xl font-semibold">
35+
<Link href={`/products-db/${product.id}`}>{product.title}</Link>
36+
</h2>
37+
<p>{product.description}</p>
38+
<p className="text-lg font-medium">${product.price}</p>
39+
<form action={removeProductById.bind(null, product.id)}>
40+
<button
41+
type="submit"
42+
className="px-4 py-2 mt-4 text-white bg-red-500 rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-600"
43+
>
44+
Delete
45+
</button>
46+
</form>
47+
</li>
48+
))}
49+
</ul>
50+
);
51+
};

0 commit comments

Comments
 (0)