Use startTransition for delete refresh and fix filter updates
- DeleteItemButton now uses startTransition for router.refresh() - ListDetailView re-applies filters when initialItems changes - This ensures deleted items disappear after refresh completes - Transition provides better React 18 concurrent rendering support
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useState, useTransition } from 'react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { deleteItem } from '@/lib/actions'
|
import { deleteItem } from '@/lib/actions'
|
||||||
import { Trash2 } from 'lucide-react'
|
import { Trash2 } from 'lucide-react'
|
||||||
@@ -17,18 +17,25 @@ export default function DeleteItemButton({ itemId, listId, variant = 'full' }: D
|
|||||||
const { showToast } = useToast()
|
const { showToast } = useToast()
|
||||||
const [isDeleting, setIsDeleting] = useState(false)
|
const [isDeleting, setIsDeleting] = useState(false)
|
||||||
const [showConfirm, setShowConfirm] = useState(false)
|
const [showConfirm, setShowConfirm] = useState(false)
|
||||||
|
const [isPending, startTransition] = useTransition()
|
||||||
|
|
||||||
const handleDelete = async (e: React.MouseEvent) => {
|
const handleDelete = async (e: React.MouseEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setIsDeleting(true)
|
setIsDeleting(true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await deleteItem(itemId)
|
await deleteItem(itemId)
|
||||||
showToast('Task deleted successfully', 'success')
|
showToast('Task deleted successfully', 'success')
|
||||||
|
|
||||||
|
// Reset state immediately
|
||||||
setShowConfirm(false)
|
setShowConfirm(false)
|
||||||
setIsDeleting(false)
|
setIsDeleting(false)
|
||||||
// Always refresh to update the UI
|
|
||||||
|
// Use startTransition to refresh the route
|
||||||
|
startTransition(() => {
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting item:', error)
|
console.error('Error deleting item:', error)
|
||||||
showToast('Failed to delete task', 'error')
|
showToast('Failed to delete task', 'error')
|
||||||
@@ -54,14 +61,14 @@ export default function DeleteItemButton({ itemId, listId, variant = 'full' }: D
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={handleDelete}
|
onClick={handleDelete}
|
||||||
disabled={isDeleting}
|
disabled={isDeleting || isPending}
|
||||||
className="px-3 sm:px-4 py-2 sm:py-2.5 bg-red-500 hover:bg-red-600 active:bg-red-700 disabled:bg-red-300 text-white rounded-lg text-xs sm:text-sm transition-colors tap-target-sm font-medium"
|
className="px-3 sm:px-4 py-2 sm:py-2.5 bg-red-500 hover:bg-red-600 active:bg-red-700 disabled:bg-red-300 text-white rounded-lg text-xs sm:text-sm transition-colors tap-target-sm font-medium"
|
||||||
>
|
>
|
||||||
{isDeleting ? 'Deleting...' : 'Confirm'}
|
{isDeleting || isPending ? 'Deleting...' : 'Confirm'}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
disabled={isDeleting}
|
disabled={isDeleting || isPending}
|
||||||
className="px-3 sm:px-4 py-2 sm:py-2.5 bg-gray-200 hover:bg-gray-300 active:bg-gray-400 text-gray-700 rounded-lg text-xs sm:text-sm transition-colors tap-target-sm font-medium"
|
className="px-3 sm:px-4 py-2 sm:py-2.5 bg-gray-200 hover:bg-gray-300 active:bg-gray-400 text-gray-700 rounded-lg text-xs sm:text-sm transition-colors tap-target-sm font-medium"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -144,14 +144,10 @@ export default function ListDetailView({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Update filtered items when initialItems changes (after refresh)
|
// Update filtered items when initialItems changes (after refresh)
|
||||||
useEffect(() => {
|
// Re-apply filters to the new data
|
||||||
setFilteredItems(initialItems)
|
|
||||||
}, [initialItems])
|
|
||||||
|
|
||||||
// Apply initial filters on mount
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleFiltersCallback(filters)
|
handleFiltersCallback(filters)
|
||||||
}, []) // Only run on mount
|
}, [initialItems, handleFiltersCallback, filters])
|
||||||
|
|
||||||
// Determine which items to display
|
// Determine which items to display
|
||||||
const displayItems = debouncedQuery.trim() ? searchResults : filteredItems
|
const displayItems = debouncedQuery.trim() ? searchResults : filteredItems
|
||||||
|
|||||||
Reference in New Issue
Block a user