Skip to content

Commit 3647dc4

Browse files
committed
refactor: replace renderHook with renderHookAsync
1 parent c4cedd8 commit 3647dc4

File tree

5 files changed

+56
-140
lines changed

5 files changed

+56
-140
lines changed

src/__tests__/render-hook-async.test.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { ReactNode } from 'react';
22
import * as React from 'react';
33
import { Text } from 'react-native';
44

5-
import { act, renderHookAsync } from '..';
5+
import { act, renderHook } from '..';
66
import { excludeConsoleMessage } from '../test-utils/console';
77

88
// eslint-disable-next-line no-console
@@ -18,8 +18,8 @@ function useSuspendingHook(promise: Promise<string>) {
1818
return React.use(promise);
1919
}
2020

21-
test('renderHookAsync renders hook asynchronously', async () => {
22-
const { result } = await renderHookAsync(() => {
21+
test('renderHook renders hook asynchronously', async () => {
22+
const { result } = await renderHook(() => {
2323
const [state, setState] = React.useState(1);
2424

2525
React.useEffect(() => {
@@ -32,7 +32,7 @@ test('renderHookAsync renders hook asynchronously', async () => {
3232
expect(result.current).toEqual(2);
3333
});
3434

35-
test('renderHookAsync with wrapper option', async () => {
35+
test('renderHook with wrapper option', async () => {
3636
const Context = React.createContext('default');
3737

3838
function useTestHook() {
@@ -43,7 +43,7 @@ test('renderHookAsync with wrapper option', async () => {
4343
return <Context.Provider value="provided">{children}</Context.Provider>;
4444
}
4545

46-
const { result } = await renderHookAsync(useTestHook, { wrapper: Wrapper });
46+
const { result } = await renderHook(useTestHook, { wrapper: Wrapper });
4747
expect(result.current).toEqual('provided');
4848
});
4949

@@ -58,12 +58,12 @@ test('rerenderAsync function updates hook asynchronously', async () => {
5858
return state;
5959
}
6060

61-
const { result, rerenderAsync } = await renderHookAsync(useTestHook, {
61+
const { result, rerender } = await renderHook(useTestHook, {
6262
initialProps: { value: 5 },
6363
});
6464
expect(result.current).toEqual(10);
6565

66-
await rerenderAsync({ value: 10 });
66+
await rerender({ value: 10 });
6767
expect(result.current).toEqual(20);
6868
});
6969

@@ -80,10 +80,10 @@ test('unmount function unmounts hook asynchronously', async () => {
8080
return 'test';
8181
}
8282

83-
const { unmountAsync } = await renderHookAsync(useTestHook);
83+
const { unmount } = await renderHook(useTestHook);
8484
expect(cleanupCalled).toBe(false);
8585

86-
await unmountAsync();
86+
await unmount();
8787
expect(cleanupCalled).toBe(true);
8888
});
8989

@@ -98,7 +98,7 @@ test('handles hook with state updates during effects', async () => {
9898
return count;
9999
}
100100

101-
const { result } = await renderHookAsync(useTestHook);
101+
const { result } = await renderHook(useTestHook);
102102
expect(result.current).toBe(1);
103103
});
104104

@@ -115,7 +115,7 @@ test('handles multiple state updates in effects', async () => {
115115
return { first, second };
116116
}
117117

118-
const { result } = await renderHookAsync(useTestHook);
118+
const { result } = await renderHook(useTestHook);
119119
expect(result.current).toEqual({ first: 10, second: 20 });
120120
});
121121

@@ -125,7 +125,7 @@ test('handles hook with suspense', async () => {
125125
resolvePromise = resolve;
126126
});
127127

128-
const { result } = await renderHookAsync(useSuspendingHook, {
128+
const { result } = await renderHook(useSuspendingHook, {
129129
initialProps: promise,
130130
wrapper: ({ children }) => (
131131
<React.Suspense fallback={<Text>Loading...</Text>}>{children}</React.Suspense>
@@ -168,7 +168,7 @@ test('handles hook suspense with error boundary', async () => {
168168
rejectPromise = reject;
169169
});
170170

171-
const { result } = await renderHookAsync(useSuspendingHook, {
171+
const { result } = await renderHook(useSuspendingHook, {
172172
initialProps: promise,
173173
wrapper: ({ children }) => (
174174
<ErrorBoundary fallback="error-fallback">
@@ -206,7 +206,7 @@ test('handles custom hooks with complex logic', async () => {
206206
return { count, increment, decrement, reset };
207207
}
208208

209-
const { result } = await renderHookAsync(useCounter, { initialProps: 5 });
209+
const { result } = await renderHook(useCounter, { initialProps: 5 });
210210
expect(result.current.count).toBe(5);
211211

212212
// eslint-disable-next-line require-await
@@ -247,20 +247,20 @@ test('handles hook with cleanup and re-initialization', async () => {
247247
return value;
248248
}
249249

250-
const { result, rerenderAsync, unmountAsync } = await renderHookAsync(useTestHook, {
250+
const { result, rerender, unmount } = await renderHook(useTestHook, {
251251
initialProps: { key: 'initial' },
252252
});
253253

254254
expect(result.current).toBe('initial-effect');
255255
expect(effectCount).toBe(1);
256256
expect(cleanupCount).toBe(0);
257257

258-
await rerenderAsync({ key: 'updated' });
258+
await rerender({ key: 'updated' });
259259
expect(result.current).toBe('updated-effect');
260260
expect(effectCount).toBe(2);
261261
expect(cleanupCount).toBe(1);
262262

263-
await unmountAsync();
263+
await unmount();
264264
expect(effectCount).toBe(2);
265265
expect(cleanupCount).toBe(2);
266266
});

src/__tests__/render-hook.test.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import * as React from 'react';
33

44
import { renderHook } from '../pure';
55

6-
test('gives committed result', () => {
7-
const { result } = renderHook(() => {
6+
test('gives committed result', async () => {
7+
const { result } = await renderHook(() => {
88
const [state, setState] = React.useState(1);
99

1010
React.useEffect(() => {
@@ -17,8 +17,8 @@ test('gives committed result', () => {
1717
expect(result.current).toEqual([2, expect.any(Function)]);
1818
});
1919

20-
test('allows rerendering', () => {
21-
const { result, rerender } = renderHook(
20+
test('allows rerendering', async () => {
21+
const { result, rerender } = await renderHook(
2222
(props: { branch: 'left' | 'right' }) => {
2323
const [left, setLeft] = React.useState('left');
2424
const [right, setRight] = React.useState('right');
@@ -37,17 +37,17 @@ test('allows rerendering', () => {
3737

3838
expect(result.current).toEqual(['left', expect.any(Function)]);
3939

40-
rerender({ branch: 'right' });
40+
await rerender({ branch: 'right' });
4141

4242
expect(result.current).toEqual(['right', expect.any(Function)]);
4343
});
4444

45-
test('allows wrapper components', () => {
45+
test('allows wrapper components', async () => {
4646
const Context = React.createContext('default');
4747
function Wrapper({ children }: { children: ReactNode }) {
4848
return <Context.Provider value="provided">{children}</Context.Provider>;
4949
}
50-
const { result } = renderHook(
50+
const { result } = await renderHook(
5151
() => {
5252
return React.useContext(Context);
5353
},
@@ -63,23 +63,23 @@ function useMyHook<T>(param: T) {
6363
return { param };
6464
}
6565

66-
test('props type is inferred correctly when initial props is defined', () => {
67-
const { result, rerender } = renderHook((num: number) => useMyHook(num), {
66+
test('props type is inferred correctly when initial props is defined', async () => {
67+
const { result, rerender } = await renderHook((num: number) => useMyHook(num), {
6868
initialProps: 5,
6969
});
7070
expect(result.current.param).toBe(5);
7171

72-
rerender(6);
72+
await rerender(6);
7373
expect(result.current.param).toBe(6);
7474
});
7575

76-
test('props type is inferred correctly when initial props is explicitly undefined', () => {
77-
const { result, rerender } = renderHook((num: number | undefined) => useMyHook(num), {
76+
test('props type is inferred correctly when initial props is explicitly undefined', async () => {
77+
const { result, rerender } = await renderHook((num: number | undefined) => useMyHook(num), {
7878
initialProps: undefined,
7979
});
8080

8181
expect(result.current.param).toBeUndefined();
8282

83-
rerender(6);
83+
await rerender(6);
8484
expect(result.current.param).toBe(6);
8585
});

src/pure.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export { within, getQueriesForElement } from './within';
1010
export { configure, resetToDefaults } from './config';
1111
export { isHiddenFromAccessibility, isInaccessible } from './helpers/accessibility';
1212
export { getDefaultNormalizer } from './matches';
13-
export { renderHook, renderHookAsync } from './render-hook';
13+
export { renderHook } from './render-hook';
1414
export { screen } from './screen';
1515
export { userEvent } from './user-event';
1616

@@ -21,6 +21,6 @@ export type {
2121
DebugFunction,
2222
} from './render';
2323
export type { RenderAsyncOptions, RenderAsyncResult } from './render-async';
24-
export type { RenderHookOptions, RenderHookResult, RenderHookAsyncResult } from './render-hook';
24+
export type { RenderHookOptions, RenderHookResult } from './render-hook';
2525
export type { Config } from './config';
2626
export type { UserEventConfig } from './user-event';

src/render-hook.tsx

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

3-
import render from './render';
43
import renderAsync from './render-async';
54
import type { RefObject } from './types';
65

76
export type RenderHookResult<Result, Props> = {
87
result: RefObject<Result>;
9-
rerender: (props: Props) => void;
10-
unmount: () => void;
11-
};
12-
13-
export type RenderHookAsyncResult<Result, Props> = {
14-
result: RefObject<Result>;
15-
rerenderAsync: (props: Props) => Promise<void>;
16-
unmountAsync: () => Promise<void>;
8+
rerender: (props: Props) => Promise<void>;
9+
unmount: () => Promise<void>;
1710
};
1811

1912
export type RenderHookOptions<Props> = {
@@ -30,39 +23,10 @@ export type RenderHookOptions<Props> = {
3023
wrapper?: React.ComponentType<any>;
3124
};
3225

33-
export function renderHook<Result, Props>(
34-
hookToRender: (props: Props) => Result,
35-
options?: RenderHookOptions<NoInfer<Props>>,
36-
): RenderHookResult<Result, Props> {
37-
const result = React.createRef<Result>() as RefObject<Result>;
38-
39-
function HookContainer({ hookProps }: { hookProps: Props }) {
40-
const renderResult = hookToRender(hookProps);
41-
React.useEffect(() => {
42-
result.current = renderResult;
43-
});
44-
45-
return null;
46-
}
47-
48-
const { initialProps, ...renderOptions } = options ?? {};
49-
const { rerender: rerenderComponent, unmount } = render(
50-
// @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
51-
<HookContainer hookProps={initialProps} />,
52-
renderOptions,
53-
);
54-
55-
return {
56-
result: result,
57-
rerender: (hookProps: Props) => rerenderComponent(<HookContainer hookProps={hookProps} />),
58-
unmount,
59-
};
60-
}
61-
62-
export async function renderHookAsync<Result, Props>(
26+
export async function renderHook<Result, Props>(
6327
hookToRender: (props: Props) => Result,
6428
options?: RenderHookOptions<NoInfer<Props>>,
65-
): Promise<RenderHookAsyncResult<Result, Props>> {
29+
): Promise<RenderHookResult<Result, Props>> {
6630
const result = React.createRef<Result>() as RefObject<Result>;
6731

6832
function TestComponent({ hookProps }: { hookProps: Props }) {
@@ -83,8 +47,7 @@ export async function renderHookAsync<Result, Props>(
8347

8448
return {
8549
result: result,
86-
rerenderAsync: (hookProps: Props) =>
87-
rerenderComponentAsync(<TestComponent hookProps={hookProps} />),
88-
unmountAsync,
50+
rerender: (hookProps: Props) => rerenderComponentAsync(<TestComponent hookProps={hookProps} />),
51+
unmount: unmountAsync,
8952
};
9053
}

0 commit comments

Comments
 (0)