Skip to content

Commit 6674eda

Browse files
committed
Processing state with useForm helper
1 parent 861e857 commit 6674eda

File tree

4 files changed

+43
-38
lines changed

4 files changed

+43
-38
lines changed

app/Http/Controllers/PuppyController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function index()
1919

2020
public function like(Request $request, Puppy $puppy)
2121
{
22-
sleep(3);
22+
sleep(1);
2323
$puppy->likedBy()->toggle($request->user()->id);
2424
return back();
2525
}
Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
1-
import { Link, usePage } from '@inertiajs/react';
1+
import { useForm, usePage } from '@inertiajs/react';
22
import clsx from 'clsx';
33
import { Heart, LoaderCircle } from 'lucide-react';
44
import { Puppy, SharedData } from '../types';
55

66
export function LikeToggle({ puppy }: { puppy: Puppy }) {
77
const { auth } = usePage<SharedData>().props;
8+
const { processing, patch } = useForm();
89

910
return (
10-
<Link
11-
preserveScroll
12-
method="patch"
13-
href={route('puppies.like', puppy.id)}
14-
className={clsx('group', !auth.user && 'cursor-not-allowed')}
15-
disabled={!auth.user}
11+
<form
12+
onSubmit={(e) => {
13+
e.preventDefault();
14+
patch(route('puppies.like', puppy.id), {
15+
preserveScroll: true,
16+
});
17+
}}
1618
>
17-
<LoaderCircle className="hidden animate-spin stroke-slate-300 group-data-loading:block" />
18-
<Heart
19-
className={clsx(
20-
auth.user && puppy.likedBy.includes(auth.user.id) ? 'fill-pink-500 stroke-none' : 'stroke-slate-200 group-hover:stroke-slate-300',
21-
'group-data-loading:hidden',
19+
<button type="submit" className={clsx('group', !auth.user && 'cursor-not-allowed')} disabled={!auth.user || processing}>
20+
{processing ? (
21+
<LoaderCircle className="animate-spin stroke-slate-300" />
22+
) : (
23+
<Heart
24+
className={clsx(
25+
auth.user && puppy.likedBy.includes(auth.user.id)
26+
? 'fill-pink-500 stroke-none'
27+
: 'stroke-slate-200 group-hover:stroke-slate-300',
28+
)}
29+
/>
2230
)}
23-
/>
24-
</Link>
31+
</button>
32+
</form>
2533
);
2634
}
Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import { usePage } from '@inertiajs/react';
1+
import { useForm, usePage } from '@inertiajs/react';
22
import { Heart, LoaderCircle, X } from 'lucide-react';
3-
import { Dispatch, SetStateAction, useState } from 'react';
4-
import { toggleLikedStatus } from '../queries';
53
import { Puppy, SharedData } from '../types';
64

7-
export function Shortlist({ puppies, setPuppies }: { puppies: Puppy[]; setPuppies: Dispatch<SetStateAction<Puppy[]>> }) {
5+
export function Shortlist({ puppies }: { puppies: Puppy[] }) {
86
const { auth } = usePage<SharedData>().props;
97
return (
108
<div>
@@ -22,34 +20,33 @@ export function Shortlist({ puppies, setPuppies }: { puppies: Puppy[]; setPuppie
2220
>
2321
<img height={32} width={32} alt={puppy.name} className="aspect-square w-8 object-cover" src={puppy.imageUrl} />
2422
<p className="px-3 text-sm text-slate-800">{puppy.name}</p>
25-
<DeleteButton id={puppy.id} setPuppies={setPuppies} />
23+
<DeleteButton id={puppy.id} />
2624
</li>
2725
))}
2826
</ul>
2927
</div>
3028
);
3129
}
3230

33-
function DeleteButton({ id, setPuppies }: { id: Puppy['id']; setPuppies: Dispatch<SetStateAction<Puppy[]>> }) {
34-
const [pending, setPending] = useState(false);
31+
function DeleteButton({ id }: { id: Puppy['id'] }) {
32+
const { processing, patch } = useForm();
3533
return (
36-
<button
37-
onClick={async () => {
38-
setPending(true);
39-
const updatedPuppy = await toggleLikedStatus(id);
40-
setPuppies((prevPups) => {
41-
return prevPups.map((existingPuppy) => (existingPuppy.id === updatedPuppy.id ? updatedPuppy : existingPuppy));
34+
<form
35+
className="h-full"
36+
onSubmit={(e) => {
37+
e.preventDefault();
38+
patch(route('puppies.like', id), {
39+
preserveScroll: true,
4240
});
43-
setPending(false);
4441
}}
45-
className="group h-full border-l border-slate-100 px-2 hover:bg-slate-100"
46-
disabled={pending}
4742
>
48-
{pending ? (
49-
<LoaderCircle className="size-4 animate-spin stroke-slate-300" />
50-
) : (
51-
<X className="size-4 stroke-slate-400 group-hover:stroke-red-400" />
52-
)}
53-
</button>
43+
<button type="submit" className="group h-full border-l border-slate-100 px-2 hover:bg-slate-100" disabled={processing}>
44+
{processing ? (
45+
<LoaderCircle className="size-4 animate-spin stroke-slate-300" />
46+
) : (
47+
<X className="size-4 stroke-slate-400 group-hover:stroke-red-400" />
48+
)}
49+
</button>
50+
</form>
5451
);
5552
}

resources/js/pages/puppies/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function Main({ inertiaPuppies }: { inertiaPuppies: Puppy[] }) {
3030
<main>
3131
<div className="mt-24 grid gap-8 sm:grid-cols-2">
3232
<Search searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
33-
{auth.user && <Shortlist puppies={inertiaPuppies} setPuppies={setPuppies} />}
33+
{auth.user && <Shortlist puppies={inertiaPuppies} />}
3434
</div>
3535
<PuppiesList puppies={inertiaPuppies} searchQuery={searchQuery} />
3636
<NewPuppyForm puppies={inertiaPuppies} setPuppies={setPuppies} />

0 commit comments

Comments
 (0)