Skip to content

Commit ae449f5

Browse files
committed
tweaks
1 parent ec31ded commit ae449f5

File tree

1 file changed

+43
-12
lines changed

1 file changed

+43
-12
lines changed

src/render-hook.tsx

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import * as React from 'react';
22

3-
import { renderInternal } from './render';
3+
import render from './render';
4+
import renderAsync from './render-async';
45

56
export type RenderHookResult<Result, Props> = {
7+
result: React.RefObject<Result>;
68
rerender: (props: Props) => void;
7-
result: React.MutableRefObject<Result>;
89
unmount: () => void;
910
};
1011

12+
export type RenderHookAsyncResult<Result, Props> = {
13+
result: React.RefObject<Result>;
14+
rerender: (props: Props) => Promise<void>;
15+
unmount: () => Promise<void>;
16+
};
17+
1118
export type RenderHookOptions<Props> = {
1219
/**
1320
* The initial props to pass to the hook.
@@ -32,34 +39,58 @@ export function renderHook<Result, Props>(
3239
hookToRender: (props: Props) => Result,
3340
options?: RenderHookOptions<Props>,
3441
): RenderHookResult<Result, Props> {
42+
const result: React.RefObject<Result | null> = React.createRef();
43+
44+
function HookContainer({ hookProps }: { hookProps: Props }) {
45+
const renderResult = hookToRender(hookProps);
46+
React.useEffect(() => {
47+
result.current = renderResult;
48+
});
49+
50+
return null;
51+
}
52+
3553
const { initialProps, ...renderOptions } = options ?? {};
54+
const { rerender: rerenderComponent, unmount } = render(
55+
// @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
56+
<HookContainer hookProps={initialProps} />,
57+
renderOptions,
58+
);
3659

37-
const result: React.MutableRefObject<Result | null> = React.createRef();
60+
return {
61+
// Result should already be set after the first render effects are run.
62+
result: result as React.RefObject<Result>,
63+
rerender: (hookProps: Props) => rerenderComponent(<HookContainer hookProps={hookProps} />),
64+
unmount,
65+
};
66+
}
67+
68+
export async function renderHookAsync<Result, Props>(
69+
hookToRender: (props: Props) => Result,
70+
options?: RenderHookOptions<Props>,
71+
): Promise<RenderHookAsyncResult<Result, Props>> {
72+
const result: React.RefObject<Result | null> = React.createRef();
3873

3974
function TestComponent({ hookProps }: { hookProps: Props }) {
4075
const renderResult = hookToRender(hookProps);
41-
4276
React.useEffect(() => {
4377
result.current = renderResult;
4478
});
4579

4680
return null;
4781
}
4882

49-
const { rerender: componentRerender, unmount } = renderInternal(
83+
const { initialProps, ...renderOptions } = options ?? {};
84+
const { rerenderAsync: rerenderComponentAsync, unmountAsync } = await renderAsync(
5085
// @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
5186
<TestComponent hookProps={initialProps} />,
5287
renderOptions,
5388
);
5489

55-
function rerender(hookProps: Props) {
56-
return componentRerender(<TestComponent hookProps={hookProps} />);
57-
}
58-
5990
return {
6091
// Result should already be set after the first render effects are run.
61-
result: result as React.MutableRefObject<Result>,
62-
rerender,
63-
unmount,
92+
result: result as React.RefObject<Result>,
93+
rerender: (hookProps: Props) => rerenderComponentAsync(<TestComponent hookProps={hookProps} />),
94+
unmount: unmountAsync,
6495
};
6596
}

0 commit comments

Comments
 (0)