Change useApiHolder to not throw when outside API context

Instead of throwing a NotImplementedError, useApiHolder now returns an
empty ApiHolder when no API context is available in the React tree.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-05 10:18:26 +01:00
parent d0b53e39fd
commit fe848e09e6
3 changed files with 33 additions and 7 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': patch
---
Changed `useApiHolder` to return an empty `ApiHolder` instead of throwing when used outside of an API context.
@@ -17,7 +17,30 @@
import { renderHook } from '@testing-library/react';
import { createVersionedContextForTesting } from '@backstage/version-bridge';
import { createApiRef } from './ApiRef';
import { useApi } from './useApi';
import { useApi, useApiHolder } from './useApi';
describe('useApiHolder', () => {
const context = createVersionedContextForTesting('api-context');
afterEach(() => {
context.reset();
});
it('should return the API holder from context', () => {
const holder = { get: jest.fn() };
context.set({ 1: holder });
const renderedHook = renderHook(() => useApiHolder());
expect(renderedHook.result.current).toBe(holder);
});
it('should return an empty API holder when there is no context', () => {
const renderedHook = renderHook(() => useApiHolder());
const holder = renderedHook.result.current;
expect(holder.get(createApiRef<string>({ id: 'x' }))).toBeUndefined();
});
});
describe('useApi', () => {
const context = createVersionedContextForTesting('api-context');
@@ -19,6 +19,8 @@ import { ApiRef, ApiHolder, TypesToApiRefs } from './types';
import { useVersionedContext } from '@backstage/version-bridge';
import { NotImplementedError } from '@backstage/errors';
const emptyApiHolder: ApiHolder = { get: () => undefined };
/**
* React hook for retrieving {@link ApiHolder}, an API catalog.
*
@@ -27,14 +29,10 @@ import { NotImplementedError } from '@backstage/errors';
export function useApiHolder(): ApiHolder {
const versionedHolder = useVersionedContext<{ 1: ApiHolder }>('api-context');
if (!versionedHolder) {
throw new NotImplementedError('API context is not available');
return emptyApiHolder;
}
const apiHolder = versionedHolder.atVersion(1);
if (!apiHolder) {
throw new NotImplementedError('ApiContext v1 not available');
}
return apiHolder;
return versionedHolder.atVersion(1) ?? emptyApiHolder;
}
/**