Skip to content

Commit

Permalink
Fix render-loop on loading opt-out
Browse files Browse the repository at this point in the history
  • Loading branch information
mfal committed Aug 30, 2023
1 parent 3fb6604 commit 50e33ce
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
7 changes: 4 additions & 3 deletions src/resource/getAsyncResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { defaultStorageKeyBuilder } from "../store/defaultStorageKeyBuilder.js";
import { Store } from "../store/Store.js";
import { AsyncResource, AsyncResourceOptions } from "./AsyncResource.js";

const buildEmptyResource = (options: AsyncResourceOptions) =>
new AsyncResource<undefined>(() => Promise.resolve(undefined), options);
const emptyResource = new AsyncResource<undefined>(() =>
Promise.resolve(undefined),
);

// function overloads for nullable parameters
export function getAsyncResource<TValue, TParams extends FnParameters>(
Expand All @@ -31,7 +32,7 @@ export function getAsyncResource<TValue, TParams extends FnParameters>(
};

if (parameters === null) {
return buildEmptyResource(asyncResourceOptions);
return emptyResource;
}

const storageKey = defaultStorageKeyBuilder({
Expand Down
35 changes: 30 additions & 5 deletions src/use-promise/usePromise.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,54 @@ const waitForRendered = async (count: number): Promise<void> => {
await waitFor(() => expect(renderCount).toBe(count));
};

const SquareNumberView: FC<{ value: number }> = (props) => (
interface Props {
value: number | null;
}

const SquareNumberView: FC<Props> = (props) => (
<RenderWithLoadingView>
{() => {
const { value } = props;
renderCount++;
const squareNumber = usePromise(squareAsync, [value, loadingTime]);
return <span data-testid="square-number-component">{squareNumber}</span>;

const squareNumber = usePromise(
squareAsync,
value === null ? null : [value, loadingTime],
);

const squareNumberString =
squareNumber === undefined ? "undefined" : squareNumber;

return (
<span data-testid="square-number-component">{squareNumberString}</span>
);
}}
</RenderWithLoadingView>
);

const expectRenderedNumberToBe = (number: string): void => {
const squareComponent = screen.getByTestId("square-number-component");
expect(squareComponent.textContent).toBe(number);
};

test("Loading view is triggered", async () => {
render(<SquareNumberView value={4} />);
screen.getByTestId("loading-view");
await waitForRendered(2);
});

test("usePromise() returns 'undefined' when loader parameters are 'null'", async () => {
render(<SquareNumberView value={null} />);
screen.getByTestId("loading-view");
await waitForRendered(2);
expectRenderedNumberToBe("undefined");
});

test("SquareNumber component renders after some time", async () => {
render(<SquareNumberView value={4} />);
screen.getByTestId("loading-view");
await waitForRendered(2);
const squareComponent = screen.getByTestId("square-number-component");
expect(squareComponent.textContent).toBe("16");
expectRenderedNumberToBe("16");
});

test("AsyncLoader is not called twice when already loaded", async () => {
Expand Down

0 comments on commit 50e33ce

Please sign in to comment.