Skip to content

Commit 9efe13e

Browse files
fix: expose concurrent root in render hook (#1734)
1 parent 692c55b commit 9efe13e

File tree

3 files changed

+45
-26
lines changed

3 files changed

+45
-26
lines changed

src/render-hook.tsx

+32-18
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,42 @@
1-
import type { ComponentType } from 'react';
2-
import React from 'react';
1+
import * as React from 'react';
32
import { renderInternal } from './render';
43

54
export type RenderHookResult<Result, Props> = {
65
rerender: (props: Props) => void;
7-
result: { current: Result };
6+
result: React.MutableRefObject<Result>;
87
unmount: () => void;
98
};
109

1110
export type RenderHookOptions<Props> = {
11+
/**
12+
* The initial props to pass to the hook.
13+
*/
1214
initialProps?: Props;
15+
16+
/**
17+
* Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating
18+
* reusable custom render functions for common data providers.
19+
*/
1320
// eslint-disable-next-line @typescript-eslint/no-explicit-any
14-
wrapper?: ComponentType<any>;
21+
wrapper?: React.ComponentType<any>;
22+
23+
/**
24+
* Set to `false` to disable concurrent rendering.
25+
* Otherwise `renderHook` will default to concurrent rendering.
26+
*/
27+
concurrentRoot?: boolean;
1528
};
1629

1730
export function renderHook<Result, Props>(
18-
renderCallback: (props: Props) => Result,
31+
hookToRender: (props: Props) => Result,
1932
options?: RenderHookOptions<Props>,
2033
): RenderHookResult<Result, Props> {
21-
const initialProps = options?.initialProps;
22-
const wrapper = options?.wrapper;
34+
const { initialProps, ...renderOptions } = options ?? {};
2335

2436
const result: React.MutableRefObject<Result | null> = React.createRef();
2537

26-
function TestComponent({ renderCallbackProps }: { renderCallbackProps: Props }) {
27-
const renderResult = renderCallback(renderCallbackProps);
38+
function TestComponent({ hookProps }: { hookProps: Props }) {
39+
const renderResult = hookToRender(hookProps);
2840

2941
React.useEffect(() => {
3042
result.current = renderResult;
@@ -33,18 +45,20 @@ export function renderHook<Result, Props>(
3345
return null;
3446
}
3547

36-
const { rerender: baseRerender, unmount } = renderInternal(
48+
const { rerender: componentRerender, unmount } = renderInternal(
3749
// @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
38-
<TestComponent renderCallbackProps={initialProps} />,
39-
{
40-
wrapper,
41-
},
50+
<TestComponent hookProps={initialProps} />,
51+
renderOptions,
4252
);
4353

44-
function rerender(rerenderCallbackProps: Props) {
45-
return baseRerender(<TestComponent renderCallbackProps={rerenderCallbackProps} />);
54+
function rerender(hookProps: Props) {
55+
return componentRerender(<TestComponent hookProps={hookProps} />);
4656
}
4757

48-
// @ts-expect-error result is ill typed because ref is initialized to null
49-
return { result, rerender, unmount };
58+
return {
59+
// Result should already be set after the first render effects are run.
60+
result: result as React.MutableRefObject<Result>,
61+
rerender,
62+
unmount,
63+
};
5064
}

website/docs/13.x-next/docs/api/misc/render-hook.mdx

+7-2
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,20 @@ The `props` passed into the callback will be the `initialProps` provided in the
4545

4646
A `RenderHookOptions<Props>` object to modify the execution of the `callback` function, containing the following properties:
4747

48-
### `initialProps`
48+
### `initialProps` {#initial-props}
4949

5050
The initial values to pass as `props` to the `callback` function of `renderHook`. The `Props` type is determined by the type passed to or inferred by the `renderHook` call.
5151

5252
### `wrapper`
5353

5454
A React component to wrap the test component in when rendering. This is usually used to add context providers from `React.createContext` for the hook to access with `useContext`.
5555

56-
## `RenderHookResult`
56+
### `concurrentRoot` {#concurrent-root}
57+
58+
Set to `false` to disable concurrent rendering.
59+
Otherwise, `render` will default to using concurrent rendering used in the React Native New Architecture.
60+
61+
## Result
5762

5863
```ts
5964
interface RenderHookResult<Result, Props> {

website/docs/13.x-next/docs/api/render.mdx

+6-6
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,32 @@ test('basic test', () => {
2020

2121
> When using React context providers, like Redux Provider, you'll likely want to wrap rendered component with them. In such cases, it's convenient to create your own custom `render` method. [Follow this great guide on how to set this up](https://testing-library.com/docs/react-testing-library/setup#custom-render).
2222
23-
### Options {#render-options}
23+
## Options
2424

2525
The behavior of the `render` method can be customized by passing various options as a second argument of the `RenderOptions` type:
2626

27-
#### `wrapper` option
27+
### `wrapper` option
2828

2929
```ts
3030
wrapper?: React.ComponentType<any>,
3131
```
3232

3333
This option allows you to wrap the tested component, passed as the first option to the `render()` function, in an additional wrapper component. This is useful for creating reusable custom render functions for common React Context providers.
3434

35-
#### `concurrentRoot` option {#concurrent-root}
35+
### `concurrentRoot` option {#concurrent-root}
3636

3737
Set to `false` to disable concurrent rendering.
3838
Otherwise, `render` will default to using concurrent rendering used in the React Native New Architecture.
3939

40-
#### `createNodeMock` option
40+
### `createNodeMock` option
4141

4242
```ts
4343
createNodeMock?: (element: React.Element) => unknown,
4444
```
4545

4646
This option allows you to pass `createNodeMock` option to `ReactTestRenderer.create()` method in order to allow for custom mock refs. You can learn more about this option from [React Test Renderer documentation](https://reactjs.org/docs/test-renderer.html#ideas).
4747

48-
#### `unstable_validateStringsRenderedWithinText` option
48+
### `unstable_validateStringsRenderedWithinText` option
4949

5050
```ts
5151
unstable_validateStringsRenderedWithinText?: boolean;
@@ -59,7 +59,7 @@ This **experimental** option allows you to replicate React Native behavior of th
5959

6060
React Test Renderer does not enforce this check; hence, by default, React Native Testing Library also does not check this. That might result in runtime errors when running your code on a device, while the code works without errors in tests.
6161

62-
### Result {#render-result}
62+
## Result
6363

6464
The `render` function returns the same queries and utilities as the [`screen`](docs/api/screen) object. We recommended using the `screen` object as more developer-friendly way.
6565

0 commit comments

Comments
 (0)