Skip to content

Commit

Permalink
fix: Fix useDeferredApi export (#1742)
Browse files Browse the repository at this point in the history
- It wasn't actually being exported
- Also add a DeferredApiBootstrap component to gate on loading the API
  • Loading branch information
mofojed authored Jan 25, 2024
1 parent 3312133 commit af5f5f4
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
50 changes: 50 additions & 0 deletions packages/jsapi-bootstrap/src/DeferredApiBootstrap.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { act, render } from '@testing-library/react';
import type { dh as DhType } from '@deephaven/jsapi-types';
import { TestUtils } from '@deephaven/utils';
import DeferredApiBootstrap from './DeferredApiBootstrap';
import { DeferredApiContext } from './useDeferredApi';

it('should call the error callback if no API provider wrapped', () => {
const onError = jest.fn();
render(<DeferredApiBootstrap onError={onError} />);
expect(onError).toHaveBeenCalled();
});

it('renders children if the API is loaded', () => {
const api = TestUtils.createMockProxy<DhType>();
const { queryByText } = render(
<DeferredApiContext.Provider value={api}>
<DeferredApiBootstrap>
<div>Child</div>
</DeferredApiBootstrap>
</DeferredApiContext.Provider>
);
expect(queryByText('Child')).not.toBeNull();
});

it('waits to render children until the API is loaded', async () => {
let resolveApi: (api: DhType) => void;
const apiPromise = new Promise<DhType>(resolve => {
resolveApi = resolve;
});
const deferredApi = jest.fn(() => apiPromise);
const options = { foo: 'bar' };
const { queryByText } = render(
<DeferredApiContext.Provider value={deferredApi}>
<DeferredApiBootstrap options={options}>
<div>Child</div>
</DeferredApiBootstrap>
</DeferredApiContext.Provider>
);
expect(queryByText('Child')).toBeNull();
expect(deferredApi).toHaveBeenCalledTimes(1);
expect(deferredApi).toHaveBeenCalledWith(options);

const api = TestUtils.createMockProxy<DhType>();
await act(async () => {
resolveApi(api);
await apiPromise;
});
expect(queryByText('Child')).not.toBeNull();
});
37 changes: 37 additions & 0 deletions packages/jsapi-bootstrap/src/DeferredApiBootstrap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import useDeferredApi from './useDeferredApi';
import { ApiContext } from './ApiBootstrap';

type DeferredApiBootstrapProps = React.PropsWithChildren<{
onError?: (error: unknown) => void;
/**
* Options to use when fetching the deferred API.
*/
options?: Record<string, unknown>;
}>;

/**
* Does not render children until the deferred API is resolved.
*/
export const DeferredApiBootstrap = React.memo(
({
children,
onError,
options,
}: DeferredApiBootstrapProps): JSX.Element | null => {
const [api, apiError] = useDeferredApi(options);
if (apiError != null) {
onError?.(apiError);
return null;
}
if (api == null) {
// Still waiting for the API to load
return null;
}
return <ApiContext.Provider value={api}>{children}</ApiContext.Provider>;
}
);

DeferredApiBootstrap.displayName = 'DeferredApiBootstrap';

export default DeferredApiBootstrap;
2 changes: 2 additions & 0 deletions packages/jsapi-bootstrap/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './ApiBootstrap';
export * from './ClientBootstrap';
export * from './DeferredApiBootstrap';
export * from './useApi';
export * from './useClient';
export * from './useDeferredApi';

0 comments on commit af5f5f4

Please sign in to comment.