Create a Native View
In this lesson, you'll learn how to create custom native UI components using the Expo Modules API. Native views provide better performance and access to platform-specific UI elements that aren't available in React Native.
What are Native Views?
Native views are custom UI components written in native code (Swift/Kotlin) that can be used like any other React Native component. They're useful for:
- Integrating native UI libraries
- Creating performant custom components
- Accessing platform-specific UI elements
- Building complex animations and gestures
Creating a Native View
Let's create a custom view that displays a native label with platform-specific styling.
iOS Implementation (Swift)
import ExpoModulesCore
import UIKit
public class MyCustomView: ExpoView {
let label = UILabel()
required init(appContext: AppContext? = nil) {
super.init(appContext: appContext)
setupView()
}
func setupView() {
addSubview(label)
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: centerXAnchor),
label.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
}Android Implementation (Kotlin)
package expo.modules.mymodule
import android.content.Context
import android.widget.TextView
import android.view.Gravity
import expo.modules.kotlin.views.ExpoView
class MyCustomView(context: Context) : ExpoView(context) {
private val textView = TextView(context).apply {
gravity = Gravity.CENTER
}
init {
addView(textView)
}
}Module Definition
Define your view in the module:
// iOS
public class MyModule: Module {
public func definition() -> ModuleDefinition {
Name("MyModule")
View(MyCustomView.self) {
Prop("text") { (view: MyCustomView, text: String) in
view.label.text = text
}
Events("onPress")
}
}
}// Android
class MyModule : Module() {
override fun definition() = ModuleDefinition {
Name("MyModule")
View(MyCustomView::class) {
Prop("text") { view: MyCustomView, text: String ->
view.setText(text)
}
Events("onPress")
}
}
}Using Your Native View
In your React Native code:
import { requireNativeViewManager } from "expo-modules-core";
import { View } from "react-native";
const NativeView = requireNativeViewManager("MyModule");
export function MyCustomView({ text, onPress }) {
return (
<NativeView
style={{ width: 200, height: 100 }}
text={text}
onPress={onPress}
/>
);
}Props and Events
Defining Props
Props allow you to pass data from JavaScript to native code:
Prop("text") { (view: MyCustomView, text: String) in
view.label.text = text
}
Prop("backgroundColor") { (view: MyCustomView, color: UIColor) in
view.backgroundColor = color
}Handling Events
Events allow native code to communicate back to JavaScript:
Events("onPress", "onLongPress")
// Trigger event from native code
view.onPress?([:])Best Practices
- Keep views focused and single-purpose
- Handle layout constraints properly
- Clean up resources in view lifecycle methods
- Use events for user interactions
- Provide TypeScript definitions for better DX