> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/BintzGavin/helios/llms.txt
> Use this file to discover all available pages before exploring further.

# React example

> Build Helios compositions with React hooks and JSX

This example demonstrates how to build a Helios composition using React. It showcases React-specific patterns including custom hooks for frame synchronization and JSX-based rendering.

## Setup

Install Helios core and React dependencies:

```bash theme={null}
npm install @helios-project/core react react-dom
```

## Implementation

### Custom hook for frame synchronization

Create a custom hook to subscribe to Helios frame updates:

```typescript theme={null}
// hooks/useVideoFrame.ts
import { useState, useEffect } from 'react';
import { Helios } from '@helios-project/core';

export function useVideoFrame(helios: Helios) {
    const [frame, setFrame] = useState(helios.getState().currentFrame);

    useEffect(() => {
        // Update local state when helios state changes
        const update = (state: { currentFrame: number }) => setFrame(state.currentFrame);

        // Subscribe returns an unsubscribe function
        return helios.subscribe(update);
    }, [helios]);

    return frame;
}
```

The hook uses React's `useState` to track the current frame and `useEffect` to manage the subscription lifecycle. The cleanup function automatically unsubscribes when the component unmounts.

### Main component

Build your composition using JSX and the `useVideoFrame` hook:

```tsx theme={null}
// App.tsx
import { Helios } from '@helios-project/core';
import { useVideoFrame } from './hooks/useVideoFrame';

const duration = 5;
const fps = 30;
const helios = new Helios({ duration, fps });

// Bind to document timeline so it can be driven by the player/renderer
helios.bindToDocumentTimeline();

// Expose to window for debugging/player control
if (typeof window !== 'undefined') {
    (window as any).helios = helios;
}

export default function App() {
    const frame = useVideoFrame(helios);

    // Calculate animation values
    const progress = frame / (duration * fps);

    // Example: Opacity 0->1 over first second (30 frames)
    const opacity = Math.min(1, frame / 30);

    // Example: Scale pulse
    const scale = 1 + Math.sin(progress * Math.PI * 4) * 0.2; // 2 pulses

    // Example: Rotation
    const rotation = progress * 360;

    return (
        <div style={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            height: '100%',
            color: 'white',
            fontFamily: 'sans-serif'
        }}>
            <div style={{
                width: 200,
                height: 200,
                backgroundColor: '#61dafb',
                borderRadius: 20,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                opacity: opacity,
                transform: `scale(${scale}) rotate(${rotation}deg)`,
                boxShadow: '0 0 20px rgba(97, 218, 251, 0.5)'
            }}>
                <span style={{
                    fontSize: '2rem',
                    fontWeight: 'bold',
                    color: '#282c34',
                    transform: `rotate(-${rotation}deg)` // Keep text upright
                }}>
                    React
                </span>
            </div>

            <div style={{ marginTop: 40, textAlign: 'center' }}>
                <p>Frame: {frame.toFixed(2)}</p>
                <p>Progress: {(progress * 100).toFixed(1)}%</p>
                <p>FPS: {fps}</p>
            </div>
        </div>
    );
}
```

## Key React patterns

### Hook-based state management

The `useVideoFrame` hook encapsulates Helios subscription logic and provides a clean React-style API. It automatically handles cleanup through the `useEffect` return function.

### Inline styles for dynamic animations

Calculate animation values in the component body and apply them via inline styles. This approach works well for frame-by-frame animations where values change on every render.

### Frame-based calculations

Convert frames to progress values, opacity, scale, and rotation using simple math. Each render cycle receives a new frame number, triggering recalculation of all animation values.

## Usage

Run the development server:

```bash theme={null}
npm run dev
```

The composition will render with live frame updates. The Helios instance is exposed on `window.helios` for debugging and player control.
