ruvector/studio/hooks/misc/useQueryStateWithSelect.ts
rUv 814f595995 feat(studio): Add complete RuVector Studio application
Major additions:
- Complete Next.js studio application with 1600+ components
- Docker support (Dockerfile.combined, docker-compose.yml)
- GCP deployment documentation and benchmarks
- SQL benchmark scripts for performance testing
- Sentry integration for monitoring
- Comprehensive test suite and mocks

Studio features:
- Dashboard and admin interfaces
- Data visualization components
- Authentication and user management
- API integration with RuVector backend
- Static data and public assets

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 23:04:48 +00:00

58 lines
1.8 KiB
TypeScript

import { MutableRefObject, useEffect, useMemo } from 'react'
import { parseAsString, useQueryState } from 'nuqs'
import { toast } from 'sonner'
/**
* Hook for managing URL query parameters with a custom select function and error handling.
*
* @param enabled - Whether error handling is active (shows error when selectedId exists but select returns undefined)
* @param urlKey - The query parameter key (e.g., 'edit', 'delete')
* @param select - Function to transform the selected ID into the desired value (returns undefined if not found)
* @param onError - Callback invoked when enabled is true and selectedId exists but select returns undefined
*
* @returns Object with:
* - value: The result of select(selectedId) or undefined
* - setValue: Function to set/clear the selected ID in the URL
*/
export function useQueryStateWithSelect<T>({
enabled,
urlKey,
select,
onError,
}: {
enabled: boolean
urlKey: string
select: (id: string) => T | undefined
onError: (error: Error, selectedId: string) => void
}) {
const [selectedId, setSelectedId] = useQueryState(
urlKey,
parseAsString.withOptions({ history: 'push', clearOnDefault: true })
)
const value = useMemo(() => (selectedId ? select(selectedId) : undefined), [selectedId, select])
useEffect(() => {
if (enabled && selectedId && !value) {
onError(new Error(`not found`), selectedId)
setSelectedId(null)
}
}, [enabled, onError, selectedId, setSelectedId, value])
return {
value,
setValue: setSelectedId as (value: string | null) => void,
}
}
export const handleErrorOnDelete = (
deletingIdRef: MutableRefObject<string | null>,
selectedId: string,
errorMessage: string
) => {
if (selectedId !== deletingIdRef.current) {
toast.error(errorMessage)
} else {
deletingIdRef.current = null
}
}