React (JavaScript library)
Build TelemetryOS applications with React using the SDK's React-specific hooks and components
React Development
React is an open-source JavaScript library for building user interfaces, developed and maintained by Meta. React uses a component-based architecture and a virtual DOM to efficiently render and update UI elements, making it ideal for building interactive, data-driven applications. The TelemetryOS SDK provides first-class React support through custom hooks and components.
Build TelemetryOS applications with React using the SDK's React-specific hooks and components. The SDK provides optimized React integrations for store state management and Settings UI components that match the Studio design system.
Prerequisites
- Familiarity with React and TypeScript
- Understanding of TelemetryOS application architecture
- SDK installed:
@telemetryos/sdk
React Imports
The SDK provides two import paths:
// Core SDK (works with any framework)
import { configure, store, proxy, media } from '@telemetryos/sdk'
// React-specific hooks and components
import { useStoreState, createUseStoreState, SettingsContainer } from '@telemetryos/sdk/react'Project Structure
project-root/
├── telemetry.config.json # Platform configuration
├── package.json
├── tsconfig.json
├── vite.config.ts
├── index.html
└── src/
├── main.tsx # Entry point (configure SDK here)
├── App.tsx # Routing logic
├── views/
│ ├── Settings.tsx # /settings mount point
│ └── Render.tsx # /render mount point
├── components/ # Reusable components
├── hooks/
│ └── store.ts # Store state hooks (createUseStoreState)
├── types/ # TypeScript interfaces
└── utils/ # Helper functions
Complete File Implementations
src/main.tsx (Entry Point)
import { configure } from '@telemetryos/sdk';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
// Configure SDK ONCE before React renders
// Name must match telemetry.config.json
configure('app-name');
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);src/App.tsx (Routing)
import Settings from './views/Settings';
import Render from './views/Render';
export default function App() {
const path = window.location.pathname;
if (path === '/settings') return <Settings />;
if (path === '/render') return <Render />;
return <div>Invalid mount point: {path}</div>;
}src/hooks/store.ts (Store Hooks)
import { createUseStoreState } from '@telemetryos/sdk/react'
// Create typed hooks for each store key
export const useTeamStoreState = createUseStoreState<string>('team', '')
export const useLeagueStoreState = createUseStoreState<string>('league', 'nfl')src/views/Settings.tsx (Complete Reference)
import { store } from '@telemetryos/sdk'
import {
SettingsContainer,
SettingsField,
SettingsLabel,
SettingsInputFrame,
SettingsSelectFrame,
} from '@telemetryos/sdk/react'
import { useTeamStoreState, useLeagueStoreState } from '../hooks/store'
export default function Settings() {
const [isLoadingTeam, team, setTeam] = useTeamStoreState(store().instance)
const [isLoadingLeague, league, setLeague] = useLeagueStoreState(store().instance)
return (
<SettingsContainer>
<SettingsField>
<SettingsLabel>Team Name</SettingsLabel>
<SettingsInputFrame>
<input
type="text"
placeholder="Enter team name..."
disabled={isLoadingTeam}
value={team}
onChange={(e) => setTeam(e.target.value)}
/>
</SettingsInputFrame>
</SettingsField>
<SettingsField>
<SettingsLabel>League</SettingsLabel>
<SettingsSelectFrame>
<select
disabled={isLoadingLeague}
value={league}
onChange={(e) => setLeague(e.target.value)}
>
<option value="nfl">NFL</option>
<option value="nba">NBA</option>
<option value="mlb">MLB</option>
<option value="nhl">NHL</option>
</select>
</SettingsSelectFrame>
</SettingsField>
</SettingsContainer>
)
}src/views/Render.tsx (Complete Reference)
import { useEffect, useState } from 'react'
import { proxy } from '@telemetryos/sdk'
import { store } from '@telemetryos/sdk'
import { useTeamStoreState, useLeagueStoreState } from '../hooks/store'
interface GameScore {
homeTeam: string
awayTeam: string
homeScore: number
awayScore: number
status: string
}
export default function Render() {
// Use same hooks as Settings - automatically syncs when Settings changes
const [isLoadingTeam, team] = useTeamStoreState(store().instance)
const [isLoadingLeague, league] = useLeagueStoreState(store().instance)
const [score, setScore] = useState<GameScore | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
// Fetch scores when config changes
useEffect(() => {
if (!team) return
const fetchScore = async () => {
setLoading(true)
setError(null)
try {
// Platform handles caching automatically - no manual cache needed
const response = await proxy().fetch(
`https://api.sportsdata.io/v3/${league}/scores/json/GamesByTeam/${team}`
)
if (!response.ok) throw new Error(`API error: ${response.status}`)
const data = await response.json()
if (data.length > 0) {
const game = data[0]
setScore({
homeTeam: game.HomeTeam,
awayTeam: game.AwayTeam,
homeScore: game.HomeScore,
awayScore: game.AwayScore,
status: game.Status,
})
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error')
} finally {
setLoading(false)
}
}
fetchScore()
}, [team, league])
// Loading state
if (isLoadingTeam || isLoadingLeague) return <div>Loading config...</div>
if (!team) return <div>Configure team in Settings</div>
if (loading && !score) return <div>Loading scores...</div>
if (error && !score) return <div>Error: {error}</div>
return (
<div>
<h1>{team} - {league.toUpperCase()}</h1>
{score && (
<div>
<div>{score.awayTeam} @ {score.homeTeam}</div>
<div>{score.awayScore} - {score.homeScore}</div>
<div>{score.status}</div>
</div>
)}
</div>
)
}Quick Links
- Store Hooks -
useStoreStateandcreateUseStoreStatefor reactive store state - UI Scale Hooks - Responsive UI scaling for digital signage displays
- Settings Components - UI components for building Settings views
- Patterns & Best Practices - React patterns, error handling, and code style
Updated 23 days ago