Skip to content

Commit

Permalink
catalog-react: remove deprecated loading state of useEntity
Browse files Browse the repository at this point in the history
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
  • Loading branch information
Rugvip committed Mar 15, 2022
1 parent 456f32a commit 1f2757b
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .changeset/thin-candles-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': minor
---

**BREAKING**: The `useEntity` hook no longer returns loading or error states, and will throw an error if the entity is not immediately available. In practice this means that `useEntity` can only be used in contexts where the entity is guaranteed to have been loaded, for example inside an `EntityLayout`. To access the loading state of the entity, use `useAsyncEntity` instead.
3 changes: 0 additions & 3 deletions plugins/catalog-react/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,6 @@ export function useAsyncEntity<
// @public
export function useEntity<TEntity extends Entity = Entity>(): {
entity: TEntity;
loading: boolean;
error?: Error;
refresh?: VoidFunction;
};

// @public
Expand Down
27 changes: 13 additions & 14 deletions plugins/catalog-react/src/hooks/useEntity.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@

import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { useEntity, EntityProvider, AsyncEntityProvider } from './useEntity';
import {
useEntity,
useAsyncEntity,
EntityProvider,
AsyncEntityProvider,
} from './useEntity';
import { Entity } from '@backstage/catalog-model';

describe('EntityProvider', () => {
it('should provide no entity', async () => {
describe('useEntity', () => {
it('should throw if no entity is provided', async () => {
const { result } = renderHook(() => useEntity(), {
wrapper: ({ children }) => <EntityProvider children={children} />,
});

expect(result.current.entity).toBe(undefined);
expect(result.current.loading).toBe(true);
expect(result.current.error).toBe(undefined);
expect(result.current.refresh).toBe(undefined);
expect(result.error?.message).toMatch(/entity has not been loaded/);
});

it('should provide an entity', async () => {
Expand All @@ -40,15 +42,12 @@ describe('EntityProvider', () => {
});

expect(result.current.entity).toBe(entity);
expect(result.current.loading).toBe(false);
expect(result.current.error).toBe(undefined);
expect(result.current.refresh).toBe(undefined);
});
});

describe('AsyncEntityProvider', () => {
describe('useAsyncEntity', () => {
it('should provide no entity', async () => {
const { result } = renderHook(() => useEntity(), {
const { result } = renderHook(() => useAsyncEntity(), {
wrapper: ({ children }) => (
<AsyncEntityProvider loading={false} children={children} />
),
Expand All @@ -63,7 +62,7 @@ describe('AsyncEntityProvider', () => {
it('should provide an entity', async () => {
const entity = { kind: 'MyEntity' } as Entity;
const refresh = () => {};
const { result } = renderHook(() => useEntity(), {
const { result } = renderHook(() => useAsyncEntity(), {
wrapper: ({ children }) => (
<AsyncEntityProvider
loading={false}
Expand All @@ -82,7 +81,7 @@ describe('AsyncEntityProvider', () => {

it('should provide an error', async () => {
const error = new Error('oh no');
const { result } = renderHook(() => useEntity(), {
const { result } = renderHook(() => useAsyncEntity(), {
wrapper: ({ children }) => (
<AsyncEntityProvider
loading={false}
Expand Down
18 changes: 3 additions & 15 deletions plugins/catalog-react/src/hooks/useEntity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,6 @@ export const EntityProvider = ({ entity, children }: EntityProviderProps) => (
*/
export function useEntity<TEntity extends Entity = Entity>(): {
entity: TEntity;
/** @deprecated use {@link useAsyncEntity} instead */
loading: boolean;
/** @deprecated use {@link useAsyncEntity} instead */
error?: Error;
/** @deprecated use {@link useAsyncEntity} instead */
refresh?: VoidFunction;
} {
const versionedHolder =
useVersionedContext<{ 1: EntityLoadingStatus }>('entity-context');
Expand All @@ -123,18 +117,12 @@ export function useEntity<TEntity extends Entity = Entity>(): {
}

if (!value.entity) {
// Once we have removed the additional fields from being returned we can drop this deprecation
// and move to the error instead.
// throw new Error('useEntity hook is being called outside of an EntityLayout where the entity has not been loaded. If this is intentional, please use useAsyncEntity instead.');

// eslint-disable-next-line no-console
console.warn(
'DEPRECATION: useEntity hook is being called outside of an EntityLayout where the entity has not been loaded. If this is intentional, please use useAsyncEntity instead. This warning will be replaced with an error in future releases.',
throw new Error(
'useEntity hook is being called outside of an EntityLayout where the entity has not been loaded. If this is intentional, please use useAsyncEntity instead.',
);
}

const { entity, loading, error, refresh } = value;
return { entity: entity as TEntity, loading, error, refresh };
return { entity: value.entity as TEntity };
}

/**
Expand Down
6 changes: 3 additions & 3 deletions plugins/catalog-react/src/hooks/useEntityPermission.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common';
import { renderHook } from '@testing-library/react-hooks';
import { useEntityPermission } from './useEntityPermission';
import { useEntity } from './useEntity';
import { useAsyncEntity } from './useEntity';
import { usePermission } from '@backstage/plugin-permission-react';

jest.mock('./useEntity', () => ({
...jest.requireActual('./useEntity'),
useEntity: jest.fn(),
useAsyncEntity: jest.fn(),
}));
jest.mock('@backstage/plugin-permission-react', () => ({
...jest.requireActual('@backstage/plugin-permission-react'),
usePermission: jest.fn(),
}));
const useEntityMock = useEntity as jest.Mock;
const useEntityMock = useAsyncEntity as jest.Mock;
const usePermissionMock = usePermission as jest.Mock;

describe('useEntityPermission', () => {
Expand Down
8 changes: 6 additions & 2 deletions plugins/catalog-react/src/hooks/useEntityPermission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { stringifyEntityRef } from '@backstage/catalog-model';
import { Permission } from '@backstage/plugin-permission-common';
import { usePermission } from '@backstage/plugin-permission-react';
import { useEntity } from './useEntity';
import { useAsyncEntity } from './useEntity';

/**
* A thin wrapper around the
Expand All @@ -35,7 +35,11 @@ export function useEntityPermission(permission: Permission): {
allowed: boolean;
error?: Error;
} {
const { entity, loading: loadingEntity, error: entityError } = useEntity();
const {
entity,
loading: loadingEntity,
error: entityError,
} = useAsyncEntity();
const {
allowed,
loading: loadingPermission,
Expand Down

0 comments on commit 1f2757b

Please sign in to comment.