Skip to content

Commit 5dc36e3

Browse files
yungsterslunaleaps
andauthored
Add experimental documentation for VirtualView (#4690)
* Add experimental documentation for `VirtualView` * Revert unnecessary bold formatting * Fix missing hyperlinks and minor nits * Format with Prettier * Update docs/virtualview.md Fix space * Clarify description for `thresholdRect` --------- Co-authored-by: Luna <[email protected]>
1 parent 1f5beb7 commit 5dc36e3

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

docs/virtualview.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
id: virtualview
3+
title: VirtualView ⚗️
4+
---
5+
6+
:::important
7+
**This API is experimental.** Experimental APIs may contain bugs and are likely to change in a future version of React Native. Don't use them in production.
8+
:::
9+
10+
`VirtualView` is a core component that behaves similar to [`View`](view).
11+
12+
When it is the descendent of a [`ScrollView`](scrollview), it gains additional virtualization capabilities to reduce its memory footprint when obscured by the scroll viewport.
13+
14+
```tsx
15+
<ScrollView>
16+
<VirtualView>
17+
<Text>Hello world!</Text>
18+
</VirtualView>
19+
</ScrollView>
20+
```
21+
22+
A `VirtualView` without an ancestor[`ScrollView`](scrollview) does not have any virtualization capabilities.
23+
24+
## Virtualization
25+
26+
When a `VirtualView` leaves the visible region of a [`ScrollView`](scrollview), it becomes hidden. When hidden, a `VirtualView` will cache its most recent layout and may unmount its children — a process called virtualization.
27+
28+
When a `VirtualView` returns to the visible region of a [`ScrollView`](scrollview), it becomes visible. When visible, its children are _guaranteed_ to be rendered. This guarantee is maintained by blocking the main thread from rendering the next frame that would reveal the `VirtualView` until its children can be rendered.
29+
30+
<img src="/docs/assets/d_virtualview_modes.svg" width="700" alt="Diagram of VirtualView modes and thresholds." />
31+
32+
:::note
33+
In future developments, a hidden `VirtualView` may instead render its children in an [`<Activity mode="hidden">`](https://react.dev/reference/react/Activity) to preserve state for as long as possible while balancing memory overhead.
34+
:::
35+
36+
### Blocking the Main Thread
37+
38+
This is the first time in React Native’s feature set where rendering a React component can block the main thread. This is a new capability enabled by the [New Architecture](/architecture/landing-page)!
39+
40+
Blocking the main thread can provide a better user experience by preventing flashes of blank frames that sometimes occur when using components like [`FlatList`](flatlist). It can also enable better performance by using main thread priority, which is also typically run on higher performance cores.
41+
42+
However, blocking the main thread also comes with tradeoffs. If an update operation, such as mounting the children of a `VirtualView`, takes too long to finish, it can now drop frames. Dropping more than a couple frames can lead to a worse user experience by making the app feel sluggish and non-responsive. Dropping too many frames may cause the operating system to display a modal indicating the app is not responsive, or it may even terminate your app!
43+
44+
### Prerendering
45+
46+
`VirtualView` enables you to benefit from main thread rendering while mitigating the disadvantages of dropped frames by rendering earlier before it is needed. This is called “prerendering”.
47+
48+
By default, each `VirtualView` will prerender its children when it approaches the visible region of a [`ScrollView`](scrollview). When this happens, its children will be rendered on a background thread at a lower priority (using a [transition](https://react.dev/reference/react/startTransition)). This ensures that the main thread and React are available to handle other critical user interactions at a higher priority.
49+
50+
:::note
51+
`VirtualView`'s prerender logic is not currently configurable. The algorithm for determining this is undergoing active design iteration and is likely to change in a future release.
52+
:::
53+
54+
---
55+
56+
## Props
57+
58+
### `children`
59+
60+
Content to render inside this `VirtualView`.
61+
62+
| Type |
63+
| ------------------------ |
64+
| [React Node](react-node) |
65+
66+
---
67+
68+
### `onModeChange`
69+
70+
Invoked when the `VirtualView` changes how it renders its children.
71+
72+
If a callback is supplied, it may be invoked from different threads and priorities depending on the internal state change. This can be detected by checking the `mode` property on the event:
73+
74+
- If `mode` is [`VirtualViewMode.Visible`](#virtualviewmode), the callback is being invoked from the main thread with immediate priority.
75+
- If `mode` is [`VirtualViewMode.Prerender`](#virtualviewmode) or [`VirtualViewMode.Hidden`](#virtualviewmode), the callback is being invoked from a background thread with transition priority.
76+
77+
The callback will never be invoked consecutively with the same `mode` value. However, there are few guarantees about sequencing of events. Also, the callback may never be invoked with [`VirtualViewMode.Visible`](#virtualviewmode) even if it becomes visible, if the children were successfully prerendered.
78+
79+
| Type |
80+
| -------------------------------------------------- |
81+
| `md ([ModeChangeEvent](#modechangeevent)) => void` |
82+
83+
---
84+
85+
### `nativeID`
86+
87+
An identifier for locating this view from native classes.
88+
89+
| Type |
90+
| ------ |
91+
| string |
92+
93+
---
94+
95+
### `style`
96+
97+
| Type |
98+
| ------------------------------ |
99+
| [View Style](view-style-props) |
100+
101+
---
102+
103+
## Type Definitions
104+
105+
### `ModeChangeEvent`
106+
107+
Argument supplied to [`onModeChange`](#onmodechange).
108+
109+
| Type |
110+
| ------ |
111+
| object |
112+
113+
**Properties:**
114+
115+
| Name | Type | Description |
116+
| ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------- |
117+
| mode | [VirtualViewMode](#virtualviewmode) | New mode of the `VirtualView`. |
118+
| target | element | `VirtualView` emitting this event. |
119+
| targetRect | [Rect](rect) | Layout of `target` relative to the nearest ancestor `ScrollView`. |
120+
| thresholdRect | [Rect](rect) | Layout of the threshold that triggered this event, relative to the nearest ancestor `ScrollView`. |
121+
122+
:::note
123+
For example, if a `VirtualView` enters the visible region of a [`ScrollView`](scrollview)...
124+
125+
- `mode` would be [`VirtualViewMode.Visible`](#virtualviewmode)
126+
- `thresholdRect` would describe the visible viewport of the nearest ancestor [`ScrollView`](scrollview)
127+
- `targetRect` would be the layout of `target` that overlaps with `thresholdRect` (i.e. it is within the visible region of the [`ScrollView`](scrollview))
128+
129+
:::
130+
131+
### `VirtualViewMode`
132+
133+
Possible modes of a `VirtualView`.
134+
135+
| Name | Value | Description |
136+
| --------- | ----- | ---------------------------------------------- |
137+
| Visible | `0` | Target view is visible. |
138+
| Prerender | `1` | Target view is hidden, but can be prerendered. |
139+
| Hidden | `2` | Target view is hidden. |
140+
141+
---
142+
143+
## Static Methods
144+
145+
### `createHiddenVirtualView()`
146+
147+
```tsx
148+
static createHiddenVirtualView(height: number): typeof VirtualView;
149+
```
150+
151+
`VirtualView` initially renders its children as visible, even if it is initially obscured by an ancestor [`ScrollView`](scrollview). This is because when a component is initially rendered, the presence of an ancestor [`ScrollView`](scrollview) — let alone its size and scroll position — are unknown.
152+
153+
For advanced use cases, `createHiddenVirtualView()` creates a component that renders an initially hidden `VirtualView` with the supplied estimated layout.
154+
155+
```tsx
156+
const HiddenVirtualView = createHiddenVirtualView(100);
157+
158+
<ScrollView>
159+
<HiddenVirtualView>
160+
<Text>Hello world!</Text>
161+
</HiddenVirtualView>
162+
</ScrollView>;
163+
```
164+
165+
**Parameters:**
166+
167+
| Name | Type | Description |
168+
| ------------------------------------------------------- | ------ | ------------------------------------------------------ |
169+
| height <div class="label basic required">Required</div> | number | Estimated height of initially rendering `VirtualView`. |

website/static/docs/assets/d_virtualview_modes.svg

Lines changed: 2 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)