CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-expo

The Expo SDK provides a comprehensive set of libraries and tools for building cross-platform mobile applications using React Native.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

dom-components.mddocs/

DOM Components

The Expo DOM component system enables React Native applications to render DOM components within WebView contexts. This system provides a bridge between React Native and web technologies, allowing developers to create hybrid components that can access DOM APIs while integrating seamlessly with React Native applications.

Capabilities

DOM Component Registration

Register a React component as a DOM component that runs within a WebView context.

/**
 * Registers a React component to run as a DOM component within a WebView
 * @param AppModule - React component to register as the DOM component root
 */
function registerDOMComponent(AppModule: any): void;

DOM Imperative Handle

Create imperative handles for DOM components that can be called from the React Native side.

/**
 * React hook for creating imperative handles in DOM components
 * @param ref - React ref to bind the handle to
 * @param init - Function that creates the imperative handle object
 * @param deps - Dependency array for recreating the handle
 */
function useDOMImperativeHandle<T extends DOMImperativeFactory>(
  ref: Ref<T>,
  init: () => T,
  deps?: DependencyList
): void;

DOM Environment Detection

Utility to detect if code is running in a DOM component context.

/**
 * Constant indicating if the current environment is a DOM component
 */
const IS_DOM: boolean;

Types

/**
 * Interface for imperative handle factories in DOM components
 */
interface DOMImperativeFactory {
  [key: string]: (...args: JSONValue[]) => void;
}

/**
 * Props interface for DOM components with WebView configuration
 */
interface DOMProps extends Omit<RNWebViewProps, 'source'> {
  /** Whether to resize the native WebView size based on the DOM content size */
  matchContents?: boolean;
  /** Whether to use @expo/dom-webview as the underlying WebView implementation */
  useExpoDOMWebView?: boolean;
}

/**
 * Supported JSON value types for DOM component communication
 */
type JSONValue = boolean | number | string | null | JSONArray | JSONObject;

interface JSONArray extends Array<JSONValue> {}

interface JSONObject {
  [key: string]: JSONValue | undefined;
}

/**
 * Message structure for communication between React Native and DOM components
 */
type BridgeMessage<TData extends JSONValue> = {
  type: string;
  data: TData;
};

Usage Examples

Basic DOM Component

import React from 'react';
import { registerDOMComponent, useDOMImperativeHandle } from 'expo/dom';

interface CanvasComponentProps {
  width: number;
  height: number;
  backgroundColor?: string;
}

interface CanvasHandle {
  drawCircle: (x: number, y: number, radius: number, color: string) => void;
  clear: () => void;
  getImageData: () => string;
}

function CanvasComponent({ width, height, backgroundColor = 'white' }: CanvasComponentProps) {
  const canvasRef = React.useRef<HTMLCanvasElement>(null);
  const handleRef = React.useRef<CanvasHandle>(null);

  // Create imperative handle for React Native to call
  useDOMImperativeHandle<CanvasHandle>(
    handleRef,
    () => ({
      drawCircle: (x: number, y: number, radius: number, color: string) => {
        const canvas = canvasRef.current;
        if (!canvas) return;
        
        const ctx = canvas.getContext('2d');
        if (!ctx) return;
        
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, Math.PI * 2);
        ctx.fill();
      },
      clear: () => {
        const canvas = canvasRef.current;
        if (!canvas) return;
        
        const ctx = canvas.getContext('2d');
        if (!ctx) return;
        
        ctx.fillStyle = backgroundColor;
        ctx.fillRect(0, 0, width, height);
      },
      getImageData: () => {
        const canvas = canvasRef.current;
        if (!canvas) return '';
        
        return canvas.toDataURL();
      }
    }),
    [width, height, backgroundColor]
  );

  return (
    <canvas
      ref={canvasRef}
      width={width}
      height={height}
      style={{ backgroundColor, display: 'block' }}
    />
  );
}

// Register the component as a DOM component
registerDOMComponent(CanvasComponent);

Environment Detection

import { IS_DOM } from 'expo/dom';

function MyComponent() {
  if (IS_DOM) {
    // Code running in DOM component context
    // Has access to DOM APIs, document, window, etc.
    return (
      <div>
        <h1>DOM Component</h1>
        <p>This is running in a WebView with full DOM access</p>
      </div>
    );
  } else {
    // Code running in React Native context
    return (
      <View>
        <Text>React Native Component</Text>
      </View>
    );
  }
}

Communication Patterns

Message-Based Communication

DOM components communicate with React Native through a message-passing system:

// In DOM component
function sendMessageToReactNative(type: string, data: any) {
  // Messages are sent through the WebView bridge
  if (typeof window.ReactNativeWebView !== 'undefined') {
    window.ReactNativeWebView.postMessage(JSON.stringify({ type, data }));
  }
}

// Example: Notify React Native of user interaction
function handleUserClick(userData: any) {
  sendMessageToReactNative('user_interaction', {
    action: 'click',
    data: userData,
    timestamp: Date.now(),
  });
}

Props and State Management

// DOM components receive props from React Native
function MyDOMComponent({ initialData, onDataChange }) {
  const [data, setData] = useState(initialData);

  const handleChange = (newData) => {
    setData(newData);
    onDataChange?.(newData); // Callback to React Native
  };

  return (
    <div>
      {/* Component UI */}
    </div>
  );
}

Platform Considerations

WebView Context

DOM components run within WebView contexts, which means:

  • Full access to DOM APIs and web standards
  • Isolated JavaScript context from React Native
  • Communication happens through bridge messages
  • Performance characteristics of web rendering

Security Considerations

// DOM components should validate all data from React Native
function validateProps(props: any): boolean {
  // Implement proper validation
  return typeof props === 'object' && props !== null;
}

function SecureDOMComponent(props: any) {
  if (!validateProps(props)) {
    return <div>Invalid props provided</div>;
  }

  return (
    <div>
      {/* Safe to use props */}
    </div>
  );
}

docs

devtools.md

dom-components.md

index.md

native-modules.md

utilities.md

winter-polyfills.md

tile.json