VirtualView 🧪
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.
VirtualView
is a core component that behaves similar to View
.
When it is the descendent of a ScrollView
, it gains additional virtualization capabilities to reduce its memory footprint when obscured by the scroll viewport.
<ScrollView>
<VirtualView>
<Text>Hello world!</Text>
</VirtualView>
</ScrollView>
A VirtualView
without an ancestorScrollView
does not have any virtualization capabilities.
Virtualization
When a VirtualView
leaves the visible region of a ScrollView
, it becomes hidden. When hidden, a VirtualView
will cache its most recent layout and may unmount its children — a process called virtualization.
When a VirtualView
returns to the visible region of a 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.
In future developments, a hidden VirtualView
may instead render its children in an <Activity mode="hidden">
to preserve state for as long as possible while balancing memory overhead.
Blocking the Main Thread
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!
Blocking the main thread can provide a better user experience by preventing flashes of blank frames that sometimes occur when using components like FlatList
. It can also enable better performance by using main thread priority, which is also typically run on higher performance cores.
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!
DevTools does not currently support debugging JavaScript on the main thread. This means if you are using breakpoints to debug code called from onModeChange
, that is executed on the main thread, your debugger may freeze.
Debugging all other parts of your JavaScript code should work as expected. We are working on closing this gap before releasing VirtualView
to stable channels of React Native.
Prerendering
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”.
By default, each VirtualView
will prerender its children when it approaches the visible region of a ScrollView
. When this happens, its children will be rendered on a background thread at a lower priority (using a transition). This ensures that the main thread and React are available to handle other critical user interactions at a higher priority.
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.
Props
children
Content to render inside this VirtualView
.
Type |
---|
React Node |
onModeChange
Invoked when the VirtualView
changes how it renders its children.
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:
- If
mode
isVirtualViewMode.Visible
, the callback is being invoked from the main thread with immediate priority. - If
mode
isVirtualViewMode.Prerender
orVirtualViewMode.Hidden
, the callback is being invoked from a background thread with transition priority.
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
even if it becomes visible, if the children were successfully prerendered.
Type |
---|
(ModeChangeEvent) => void |
nativeID
An identifier for locating this view from native classes.
Type |
---|
string |
style
Type |
---|
View Style |
Type Definitions
ModeChangeEvent
Argument supplied to onModeChange
.
Type |
---|
object |
Properties:
Name | Type | Description |
---|---|---|
mode | VirtualViewMode | New mode of the VirtualView . |
target | element | VirtualView emitting this event. |
targetRect | Rect | Layout of target relative to the nearest ancestor ScrollView . |
thresholdRect | Rect | Layout of the threshold that triggered this event, relative to the nearest ancestor ScrollView . |
For example, if a VirtualView
enters the visible region of a ScrollView
...
mode
would beVirtualViewMode.Visible
thresholdRect
would describe the visible viewport of the nearest ancestorScrollView
targetRect
would be the layout oftarget
that overlaps withthresholdRect
(i.e. it is within the visible region of theScrollView
)
VirtualViewMode
Possible modes of a VirtualView
.
Name | Value | Description |
---|---|---|
Visible | 0 | Target view is visible. |
Prerender | 1 | Target view is hidden, but can be prerendered. |
Hidden | 2 | Target view is hidden. |
Static Methods
createHiddenVirtualView()
static createHiddenVirtualView(height: number): typeof VirtualView;
VirtualView
initially renders its children as visible, even if it is initially obscured by an ancestor ScrollView
. This is because when a component is initially rendered, the presence of an ancestor ScrollView
— let alone its size and scroll position — are unknown.
For advanced use cases, createHiddenVirtualView()
creates a component that renders an initially hidden VirtualView
with the supplied estimated layout.
const HiddenVirtualView = createHiddenVirtualView(100);
<ScrollView>
<HiddenVirtualView>
<Text>Hello world!</Text>
</HiddenVirtualView>
</ScrollView>;
Parameters:
Name | Type | Description |
---|---|---|
height Required | number | Estimated height of initially rendering VirtualView . |