Skip to main content
Version: Next

VirtualView 🧪

Experimental 🧪

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.

tsx
<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.

Diagram of VirtualView modes and thresholds.
note

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!

warning

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.

note

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.


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:

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 Definitions

ModeChangeEvent

Argument supplied to onModeChange.

Type
object

Properties:

NameTypeDescription
modeVirtualViewModeNew mode of the VirtualView.
targetelementVirtualView emitting this event.
targetRectRectLayout of target relative to the nearest ancestor ScrollView.
thresholdRectRectLayout of the threshold that triggered this event, relative to the nearest ancestor ScrollView.
note

For example, if a VirtualView enters the visible region of a ScrollView...

  • mode would be VirtualViewMode.Visible
  • thresholdRect would describe the visible viewport of the nearest ancestor ScrollView
  • targetRect would be the layout of target that overlaps with thresholdRect (i.e. it is within the visible region of the ScrollView)

VirtualViewMode

Possible modes of a VirtualView.

NameValueDescription
Visible0Target view is visible.
Prerender1Target view is hidden, but can be prerendered.
Hidden2Target view is hidden.

Static Methods

createHiddenVirtualView()

tsx
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.

tsx
const HiddenVirtualView = createHiddenVirtualView(100);

<ScrollView>
<HiddenVirtualView>
<Text>Hello world!</Text>
</HiddenVirtualView>
</ScrollView>;

Parameters:

NameTypeDescription
height
Required
numberEstimated height of initially rendering VirtualView.