This project demonstrates a critical limitation with Expo's DOM Components feature: DOM components do not support Over-The-Air (OTA) updates and will fail to render after an OTA update is deployed, particularly on iOS devices.
When using Expo's DOM Components (components marked with 'use dom'
directive) in your React Native app, you'll encounter the following issues after publishing an OTA update:
- DOM components fail to render after the OTA update is applied
- CSS styles are not loaded properly
- "URL not found" errors appear on iOS devices
- The native parts of your app continue to work, but DOM components become blank or broken
This project contains:
- A Lexical rich text editor implemented as a DOM component (
dom-components/hello-dom.tsx
) - CSS styles for the editor (
dom-components/styles.css
) - A native React Native screen that embeds the DOM component (
app/index.tsx
)
dom-components/
├── hello-dom.tsx # DOM component with 'use dom' directive
├── styles.css # CSS styles for the DOM component
├── ExampleTheme.ts # Lexical editor theme
└── plugins/
└── ToolbarPlugin.tsx # Editor toolbar
-
Initial Setup:
npm install npx expo start
-
Test Locally:
- The DOM component (rich text editor) works perfectly in development
- All styles load correctly
- Full functionality is available
-
Build and Deploy:
# Build the app npx expo build:ios # or build:android # Publish an OTA update npx expo publish
-
Install and Test:
- Install the built app on a device
- Verify the DOM component works initially
- Trigger the OTA update
- Observe: DOM component stops rendering after the update
- DOM components should continue working after OTA updates
- CSS styles should load properly
- Rich text editor should remain functional
- DOM components become blank/broken after OTA updates
- CSS files return "URL not found" errors
- Native components continue working normally
- Users see a degraded experience
According to the official Expo documentation:
DOM components can currently only be embedded and do not support OTA updates. This functionality may be added in the future as part of React Server Components.
- Separate JavaScript Contexts: DOM components run in isolated WebView contexts
- Asset Resolution Issues: CSS and JavaScript assets for DOM components aren't properly updated via OTA
- File Path Mismatches: After OTA updates, the WebView can't locate the updated DOM component assets
- DOM components are embedded at build time
- OTA updates only affect the main React Native bundle
- WebView assets remain tied to the original build
- No automatic reconciliation between OTA updates and DOM component assets
-
Avoid DOM Components for Critical Features:
// Instead of using DOM components for essential UI // Use native React Native components import { TextInput } from 'react-native';
-
Hybrid Approach:
// Use DOM components for non-critical features only // Keep essential functionality in native components const MyComponent = () => { return ( <View> {/* Critical native UI */} <Text>Essential content</Text> {/* Optional DOM component */} {Platform.OS === 'web' ? <DOMComponent /> : <NativeFallback />} </View> ); };
-
Force Full App Updates:
- Require users to download new app versions from app stores
- Disable OTA updates when using DOM components
-
Wait for Official Support: Expo plans to add OTA support for DOM components in future releases
-
Migrate to Native Alternatives:
// Replace DOM-based rich text editors with native ones import { RichEditor } from 'react-native-pell-rich-editor';
-
Use WebView with Remote Content:
import { WebView } from 'react-native-webview'; // Host DOM content on a web server instead of embedding <WebView source={{ uri: 'https://your-server.com/editor' }} />
- Rich text editors (like this demo)
- Complex forms with custom styling
- Data visualization components
- Interactive widgets
- Static content display
- Simple informational components
- Development/debugging tools
-
For New Projects:
- Avoid DOM components for production apps requiring OTA updates
- Use native React Native components whenever possible
- Consider DOM components only for web-specific features
-
For Existing Projects:
- Audit your DOM component usage
- Plan migration to native alternatives
- Implement feature flags to disable DOM components if needed
-
For Critical Applications:
- Disable OTA updates entirely if DOM components are essential
- Implement proper error boundaries around DOM components
- Have native fallbacks ready
This demo project serves as documentation of the current limitation. If you discover additional issues or workarounds, please contribute by:
- Opening an issue with detailed reproduction steps
- Submitting PRs with additional test cases
- Sharing workarounds that have worked for your use case