Aircada React Hooks for State Synchronization

Standard React hooks to bind component views to options, datasets, event channels, and Twin-Proxy stores.
Published: 7/20/2026

React overlays observe state updates and patch adjustments back to the Vault. Rather than subscribing directly to the store, components must use these data-bound hooks to read and update Aircada configurations dynamically.

useAirStore React Hook#

React guidelines and code examples for subscribing to and patching the global Twin-Proxy state.

Use the useAirStore hook to read application state configurations and patch values back to the global Vault.

Key Constraints

1. Never Spread State in Patches: Do NOT spread existing state inside a patch (e.g. patch({ ...state, open: true })). This creates stale closures and overrides viewport calculations. Specify only the exact nested fields to update, and let the Vault handle deep-merging. Refer to the Twin-Proxy store details for underlying merge mechanics.

2. State Configuration Typing: Always provide the generic store config type parameter (e.g. useAirStore<AirStoreConfig>()) to ensure key autocompletion.

CartPanel.tsx (typescript)
import { useAirStore } from '@aircada/air-react';
import { AirStoreConfig } from './store/store.config';

export function CartPanel() {
    const [storeState, patch] = useAirStore<AirStoreConfig>();

    const toggleCart = () => {
        // 🟢 CORRECT: Deep partial patch containing only the target key
        patch({ ui: { cartOpen: !storeState.ui.cartOpen } });
    };

    return (
        <button onClick={toggleCart} className="pointer-events-auto">
            {storeState.ui.cartOpen ? 'Close Cart' : 'Open Cart'}
        </button>
    );
}
Reading state and patching partial fields using useAirStore

useAirOptions React Hook#

React guidelines and code examples for rendering and picking product options using useAirOptions.

The useAirOptions hook is the standard, data-bound hook for option selectors. It reads configuration selections, loads list details, and applies changes directly through Twin-Proxy paths.

Key Constraints

1. Never Call useAirStore for Options: Do not manually subscribe or patch option models using low-level store hooks. Let useAirOptions manage it.

2. No Raw path Strings: Never pass a raw string (e.g. 'bodyColor') to the hook. Pass the entire optionSet object imported from the auto-generated OptionsRegistry.

ColorPicker.tsx (typescript)
import { useAirOptions } from '@aircada/air-react';
import { OptionsRegistry } from '../registry/options.generated';

export function ColorPicker() {
    // Bind to the option set object directly
    const { options, isLoading, activeSelection, selectOption } = useAirOptions(
        OptionsRegistry.BALL_O_STEEL.sets.SIMPLECOLORS
    );

    if (isLoading) return <div>Loading...</div>;

    return (
        <div className="flex gap-2 pointer-events-auto">
            {options.map(row => (
                <button
                    key={row.id}
                    className={activeSelection?.id === row.id ? 'border-cyan-500' : 'border-gray-500'}
                    onClick={() => selectOption(row)}
                >
                    {row.name}
                </button>
            ))}
        </div>
    );
}
Binding Option Selection to buttons with useAirOptions

useAirDataset React Hook#

React guidelines and code examples for fetching spreadsheet rows directly from Cloud Datasets.

Use the useAirDataset hook when a component only needs to fetch lists of items (e.g. menu contents, layout descriptors) and doesn't need active Option selection tracking.

Key Constraints

1. Single Source of Truth: Never hardcode arrays or configurations that could live in a cloud spreadsheet. Maintain them in datasets.

2. Strong Typing: Always pass the generic row type parameter to the hook. Import row interfaces directly from /registry/ files.

SidebarMenu.tsx (typescript)
import { useAirDataset } from '@aircada/air-react';
import { MediaRegistry, MenuDataRow } from '../registry/media.generated';

export function SidebarMenu() {
    // Strongly typed row fetching
    const { rows, isLoading } = useAirDataset<MenuDataRow>(
        MediaRegistry.DATASETS.MAIN_MENU.id
    );

    if (isLoading) return <div>Loading...</div>;

    return (
        <ul>
            {rows.map(row => (
                <li key={row.id}>{row.Label}</li>
            ))}
        </ul>
    );
}
Fetching and mapping cloud dataset rows in React

useAirEvent React Hook#

React guidelines and code examples for broadcasting actions and payload parameters via the global event bus.

Use the useAirEvent hook to trigger transient, fire-and-forget commands (such as resetting camera states or initiating checkout animations) that do not belong in persistent option states.

Key Constraints

1. No Magic Strings: All event names must be referenced from variables imported from registry.generated.ts.

2. Strict Payload Typing: Bind the event payload type parameter explicitly to prevent transmitting malformed structures.

ResetButton.tsx (typescript)
import { useAirEvent } from '@aircada/air-react';
import { Events, EventPayloads } from '../registry/registry.generated';

export function ResetButton() {
    // Strongly typed event invocation
    const resetCameraEvent = useAirEvent<EventPayloads[typeof Events.RESET_CAMERA]>(
        Events.RESET_CAMERA
    );

    const handleReset = () => {
        resetCameraEvent.invoke({ reason: 'User requested reset' });
    };

    return <button onClick={handleReset}>Reset Camera</button>;
}
Broadcasting a strongly typed event payload in React
SEO Title: Aircada React Hooks for State Synchronization
SEO Description: An index of standard React hooks including useAirStore, useAirOptions, useAirDataset, and useAirEvent.
Index Alternates:react hooksstate bindsdata hooks