Native views

Most Expo modules need nothing from this package: requireNativeModule, EventEmitter, SharedObject and SharedRef have no React in them, so a module that only calls into native is imported and used as its own documentation says. What needs something is a module that renders. Its React wrapper reaches the Fabric component through requireNativeViewManager, which caches a host component, builds a view config for React's renderer, and derives the Fabric component's name from the module name. None of the React parts are reachable without React, and none of them are needed - the engine writes props onto the shadow node itself, and Expo's Fabric views take their props as an untyped map, so there is no codegen'd prop list to satisfy. What is left, and what this page is about, is the name.

Import
import { SegmentedControl } from '@ng-native/expo';
Template
<segmented-control> once SegmentedControl is in the component's imports

These are all on the bare @ng-native/expo import - none of them is bound to one optional module.

import {
  registerExpoView,
  registerExpoViews,
  registerNativeViews,
  expoViewName,
} from '@ng-native/expo';

The smallest thing that works

import { registerExpoViews, registerNativeViews } from '@ng-native/expo';

registerExpoViews('expo-image', 'expo-blur'); // once, before the app mounts
registerNativeViews('web-view', 'slider');
<expo-image [source]="[{ uri }]" contentFit="cover" [transition]="{ duration: 400 }" />

<expo-image> is then an element like any other, and its props are the ones the module's native view declares - the ones the React component would have passed down, after whatever resolving it does in JavaScript.

Expo's own views

registerExpoView(elementName, moduleName, options?) teaches the engine an element name for one Expo module's view: registerExpoView('expo-image', 'ExpoImage') makes <expo-image> commit as one. Call it at startup, before the first commit that uses the element - the app still has to have the module installed so the native side registers the component; this only does the JavaScript half.

options.viewName names one of several views a module has (the default view, the module's first, takes no name); options.defaultProps are props the module's React component would have applied before native saw them - expo-image resolving a contentFit string, for instance.

registerExpoViews(...elements) registers several known views at once, by element name:

registerExpoViews('expo-image', 'expo-blur', 'expo-camera');

EXPO_VIEWS is the table it reads from - the views worth knowing the names of, so an app does not have to look each one up:

Element Module view Notes
expo-image ExpoImage Takes source as a list; a single { uri } is wrapped by the caller.
expo-blur ExpoBlurView A blur of what is behind a view - the one thing CSS cannot express.
expo-video ExpoVideo (VideoView) The player is a shared object the module hands out; this is its view.
expo-camera ExpoCamera The module's default view. See Camera.
expo-symbol SymbolModule SF Symbols, iOS only.
expo-gl ExpoGL Its context is reached through an event rather than a prop.
expo-glass ExpoGlassEffect (GlassView) The iOS 26 material. Renders as a plain view where unavailable.
expo-mesh-gradient ExpoMeshGradient (MeshGradientView) The one gradient with no CSS spelling.
expo-live-photo ExpoLivePhoto (LivePhotoView) iOS only.
expo-maps-google / expo-maps-apple ExpoGoogleMaps / ExpoAppleMaps Two modules, one view each. Typed as one: Maps.

Registering one you have not installed does not error at registration time; it produces an element that commits as nothing (UnimplementedNativeView), which is why elements are named one at a time rather than all at once - finding out at startup which modules are actually present is not something JavaScript can do without importing them all.

Community views

Not every native view an Expo app reaches for is an Expo module. NATIVE_VIEWS and registerNativeViews(...elements) cover the libraries in Expo's own bundled module list, whose Fabric names are their own - whatever codegen produced from each library's spec - rather than the ViewManagerAdapter_ names registerExpoView derives:

Element Library Notes
web-view react-native-webview
slider @react-native-community/slider
date-time-picker @react-native-community/datetimepicker Android renders a dialog, iOS an inline view.
picker / picker-item @react-native-picker/picker Items are <picker-item> children.
segmented-control @react-native-segmented-control/segmented-control iOS only. See below.
masked-view @react-native-masked-view/masked-view maskElement is a prop, not a child.
pager-view react-native-pager-view The swipeable pager a tab layout is built on.
lottie-view lottie-react-native
skia-view @shopify/react-native-skia Takes an imperative picture; declarative Skia elements do not come across.
view-shot react-native-view-shot Captures whatever it wraps.

segmented-control is a view manager from before Fabric, run through the interop layer, which only installs its onChange native block when the prop is set - as React's handler does by being there. Bind (change) or nothing fires. SegmentedControl (segmented-control.ts) is a thin typed component over this element for strict templates: import it and keep registering the name - the component supplies the types, the registration is what makes the element commit.

skia-view's name is right, but worth being plain about: Skia's drawing model is React elements through a reconciler of its own, and none of that is reachable here. What the element takes is a picture, built with Skia's imperative PictureRecorder API. Anything drawn declaratively does not come across, and a component that renders nothing is what that looks like.

Deriving the name yourself

expoViewName(moduleName, viewName?) computes the exact Fabric component name requireNativeViewManager would, for a module registerExpoView does not already know about: ViewManagerAdapter_<moduleName> (or ViewManagerAdapter_<moduleName>_<viewName> for a named view), plus a per-app suffix. The suffix is the part that cannot be hardcoded: Expo Go runs many projects in one binary, so it namespaces every view name with a per-app identifier; a standalone build has none. Get it wrong and the view commits as UnimplementedNativeView with no error - the same failure mode as a misspelled name. registerExpoView calls this for you; reach for it directly only if you are registering a name some other way.

Without the module

An element registered for a module or library that is not installed commits as nothing (UnimplementedNativeView) rather than throwing - the same failure mode as a misspelled element name, so check the name and the install first.

Reference

segmented-controlcomponent@ng-native/expo
import { SegmentedControl } from '@ng-native/expo';and add SegmentedControl to the component's imports

Inputs

values
readonly string[]

selectedIndex
number

enabled
boolean

momentary
boolean

Segments do not stay selected: each is a button.

tintColor
string

The selected segment's colour.

backgroundColor
string

fontStyle
SegmentedControlFont

activeFontStyle
SegmentedControlFont

apportionsSegmentWidthsByContent
boolean

Each segment as wide as its title rather than all equal.

accessibilityLabel
string

Outputs

change
SegmentedControlChangeEvent

Angular components as native iOS and Android views, built and shipped with Expo.

An alpha. MIT licensed. Sponsor its development.

An independent project, not affiliated with or endorsed by Google, the Angular team or Expo. Angular is a trademark of Google LLC.