Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code c8914f4b38 fix: handle missing object metadata gracefully in ViewBarPageTitle
https://sonarly.com/issue/18603?type=bug

When a user navigates to a deleted or non-existent custom object URL (e.g., `/objects/batches`), `useObjectNameSingularFromPlural` throws an unhandled error that crashes the page and redirects to `/not-found`.

Fix: Replaced `useParams()` + `useObjectNameSingularFromPlural()` + `useObjectMetadataItem()` chain in `ViewBarPageTitle` with `useRecordIndexContextOrThrow()`, which provides the already-validated `objectMetadataItem` directly from context.

This is the same pattern used by every sibling component in `views/components/` (ViewBar, ViewBarDetails, ViewBarRecordFilterEffect, etc.). The previous implementation read `objectNamePlural` directly from URL params without validation, then called `useObjectNameSingularFromPlural` which throws when the object doesn't exist in metadata. The new implementation uses the context that's already set up by `RecordIndexContainerGater` → `RecordIndexContextProvider`, which only renders when a valid `objectMetadataItem` exists (RecordIndexPage.tsx guards this at lines 19-30).

This eliminates the error for users navigating to deleted custom objects via stale URLs — instead of crashing, the `RecordIndexPage` skeleton loader handles the missing metadata gracefully.
2026-03-26 08:20:54 +00:00
@@ -1,20 +1,11 @@
import { useParams } from 'react-router-dom';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
export const ViewBarPageTitle = () => {
const { objectNamePlural } = useParams();
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const { currentView } = useGetCurrentViewOnly();
const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural: objectNamePlural ?? '',
});
const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular });
const pageTitle = currentView?.name
? `${currentView?.name} - ${objectMetadataItem.labelPlural}`
: objectMetadataItem.labelPlural;