CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-legendapp--state

A super fast and powerful state management library for JavaScript and React applications with proxy-based observables and fine-grained reactivity

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

react-integration.mddocs/

React Integration

React hooks and components for building reactive user interfaces with Legend State. The React integration provides optimized rendering with minimal re-renders through fine-grained dependency tracking.

Capabilities

React Hooks

Observable Hook

Creates and manages observables within React components.

/**
 * Creates an observable state within a React component
 * @param initialValue - Initial value, function returning value, or async function
 * @returns Observable instance tied to component lifecycle
 */
function useObservable<T>(initialValue?: T | (() => T) | (() => Promise<T>)): Observable<T>;

Observe Effect Hook

Observes observable changes and runs effects when dependencies update.

/**
 * Observes changes and runs effect function when dependencies change
 * @param selector - Function that accesses observables to track
 * @param effect - Effect function to run on changes  
 */
function useObserveEffect<T>(
  selector: () => T, 
  effect: (value: T) => void
): void;

/**
 * Alternative observe hook for direct observable observation
 * @param selector - Function accessing observables
 * @param reaction - Reaction function for changes
 */
function useObserve<T>(
  selector: () => T,
  reaction: (value: T) => void
): void;

Selector Hook

Subscribes to observable values with automatic re-rendering.

/**
 * Subscribes to observable selector with automatic re-rendering
 * @param selector - Function selecting observable values
 * @returns Current value from selector
 */
function useSelector<T>(selector: () => T): T;

Computed Hook

Creates computed values within React components.

/**
 * Creates a computed value within React component
 * @param compute - Function to compute the value
 * @returns Computed value that updates automatically
 */
function useComputed<T>(compute: () => T): T;

When Hook

Provides Promise-based waiting within React components.

/**
 * Returns Promise that resolves when predicate becomes truthy
 * @param predicate - Function to evaluate
 * @param effect - Optional effect to run when resolved
 * @returns Promise resolving to truthy value
 */
function useWhen<T>(
  predicate: () => T, 
  effect?: (value: T) => void
): Promise<T>;

Observable Reducer Hook

Provides Redux-like pattern with observables.

/**
 * Creates observable state with reducer pattern
 * @param reducer - Reducer function for state updates
 * @param initialState - Initial state value
 * @returns Tuple of observable state and dispatch function
 */
function useObservableReducer<T, A>(
  reducer: (state: T, action: A) => T,
  initialState: T
): [Observable<T>, (action: A) => void];

Lifecycle Hooks

Utility hooks for component lifecycle management.

/**
 * Runs effect only once on component mount
 * @param effect - Effect function to run on mount
 */
function useEffectOnce(effect: () => void | (() => void)): void;

/**
 * Runs effect on component mount
 * @param effect - Effect function to run on mount
 */
function useMount(effect: () => void): void;

/**
 * Runs effect on component unmount
 * @param effect - Effect function to run on unmount  
 */
function useUnmount(effect: () => void): void;

/**
 * Returns whether component is currently mounted
 * @returns Boolean indicating mount status
 */
function useIsMounted(): boolean;

React Components

Reactive Components

Higher-order components that automatically re-render when observables change.

/**
 * Makes any HTML element reactive to observable changes
 * Generic component that works with all HTML elements
 */
declare const Reactive: {
  [K in keyof JSX.IntrinsicElements]: React.ComponentType<
    JSX.IntrinsicElements[K] & {
      $key?: Observable<string | number>;
    }
  >;
};

/**
 * HOC to make any component reactive to observable changes
 * @param Component - Component to make reactive
 * @returns Reactive version of the component
 */
function reactive<T extends React.ComponentType<any>>(Component: T): T;

/**
 * Configuration for reactive system
 * @param config - Configuration options
 */
function configureReactive(config: ReactiveConfig): void;

interface ReactiveConfig {
  /** Whether to track changes automatically */
  autoTrack?: boolean;
  /** Whether to use direct rendering optimizations */
  directRender?: boolean;
}

Control Flow Components

Components for conditional rendering and iteration.

/**
 * Conditional rendering component
 * @param props.if - Selector condition to evaluate
 * @param props.ifReady - Alternative selector for ready state
 * @param props.else - Optional fallback content
 * @param props.children - Content to render when condition is true
 */
function Show<T>(props: {
  if?: Selector<T>;
  ifReady?: Selector<T>;
  else?: React.ReactNode | (() => React.ReactNode);
  wrap?: React.ComponentType;
  children: React.ReactNode | ((value?: T) => React.ReactNode);
}): JSX.Element;

/**
 * Switch/case rendering component  
 * @param props.value - Observable value to switch on
 * @param props.children - Switch cases as children
 */
function Switch<T>(props: {
  value: Observable<T> | (() => T);
  children: React.ReactNode;
}): JSX.Element;

/**
 * Array iteration component with optimized rendering
 * @param props.each - Observable array, object, or Map to iterate
 * @param props.item - Component for rendering each item
 * @param props.children - Alternative render function for each item
 * @param props.optimized - Whether to use optimization
 */
function For<T, TProps = {}>(props: {
  each?: ObservableReadable<T[] | Record<any, T> | Map<any, T>>;
  item?: React.ComponentType<{ item$: Observable<T>; id?: string } & TProps>;
  itemProps?: TProps;
  children?: (item: Observable<T>, id: string | undefined) => React.ReactElement;
  optimized?: boolean;
  sortValues?: (A: T, B: T, AKey: string, BKey: string) => number;
}): JSX.Element;

/**
 * Memoized component wrapper
 * @param props.children - Function returning content to memoize
 */
function Memo<T>(props: {
  children: () => React.ReactNode;
}): JSX.Element;

/**
 * Computed value component
 * @param props.children - Function returning computed content
 */
function Computed<T>(props: {
  children: () => React.ReactNode;
}): JSX.Element;

Provider Components

Context providers for pause/resume functionality.

/**
 * Provides pause context to child components
 * @param paused - Whether to pause reactive updates
 * @returns Provider component
 */
function usePauseProvider(paused: boolean): React.ComponentType<{
  children: React.ReactNode;
}>;

Extended React Hooks

Additional hooks for common UI patterns and integrations.

/**
 * Hook for persisted observable state
 * @param key - Storage key for persistence
 * @param initialValue - Initial value if not persisted
 * @returns Persisted observable
 */
function usePersistedObservable<T>(
  key: string, 
  initialValue?: T
): Observable<T>;

/**
 * Hook for observable queries with loading/error states
 * @param queryFn - Function returning Promise of data
 * @param options - Query configuration options
 * @returns Observable query state
 */
function useObservableQuery<T>(
  queryFn: () => Promise<T>,
  options?: QueryOptions
): ObservableQuery<T>;

interface QueryOptions {
  enabled?: boolean;
  refetchInterval?: number;
  staleTime?: number;
}

interface ObservableQuery<T> {
  data: Observable<T | undefined>;
  error: Observable<Error | undefined>;
  isLoading: Observable<boolean>;
  isError: Observable<boolean>;
  refetch: () => Promise<void>;
}

/**
 * Hook for fetch operations with observable state
 * @param url - URL to fetch
 * @param options - Fetch options
 * @returns Observable fetch state
 */
function useFetch<T>(
  url: string, 
  options?: RequestInit
): ObservableFetch<T>;

interface ObservableFetch<T> {
  data: Observable<T | undefined>;
  error: Observable<Error | undefined>;
  loading: Observable<boolean>;
}

/**
 * Hook for hover state tracking
 * @returns Hover state and ref
 */
function useHover(): [Observable<boolean>, React.RefObject<HTMLElement>];

/**
 * Hook for element measurements
 * @returns Measurements and ref
 */
function useMeasure(): [
  Observable<{ width: number; height: number }>, 
  React.RefObject<HTMLElement>
];

/**
 * Creates observable from any hook
 * @param hookFn - Hook function to make observable
 * @returns Hook that returns observable
 */
function createObservableHook<T>(hookFn: () => T): () => Observable<T>;

Usage Examples:

import React from "react";
import { observable } from "@legendapp/state";
import { 
  useObservable, 
  useSelector, 
  Reactive, 
  Show, 
  For 
} from "@legendapp/state/react";

// Component with local observable state
function TodoApp() {
  const todos$ = useObservable([
    { id: 1, text: "Learn Legend State", done: false },
    { id: 2, text: "Build awesome app", done: false }
  ]);
  
  const newTodo$ = useObservable("");
  
  const addTodo = () => {
    const text = newTodo$.get().trim();
    if (text) {
      todos$.push({
        id: Date.now(),
        text,
        done: false
      });
      newTodo$.set("");
    }
  };
  
  return (
    <div>
      <input
        value={useSelector(() => newTodo$.get())}
        onChange={e => newTodo$.set(e.target.value)}
        onKeyPress={e => e.key === 'Enter' && addTodo()}
      />
      <button onClick={addTodo}>Add Todo</button>
      
      <For each={todos$} item={(todo$, index$) => (
        <Reactive.div key={todo$.id.get()}>
          <input
            type="checkbox"
            checked={todo$.done.get()}
            onChange={e => todo$.done.set(e.target.checked)}
          />
          <span style={{
            textDecoration: todo$.done.get() ? 'line-through' : 'none'
          }}>
            {todo$.text.get()}
          </span>
          <button onClick={() => todos$.splice(index$.get(), 1)}>
            Delete
          </button>
        </Reactive.div>
      )} />
      
      <Show if={() => todos$.get().length === 0}>
        <p>No todos yet!</p>
      </Show>
    </div>
  );
}

// Global state example
const appState$ = observable({
  user: null,
  theme: "light",
  notifications: []
});

function Header() {
  const theme = useSelector(() => appState$.theme.get());
  
  return (
    <Reactive.header className={`header theme-${theme}`}>
      <Show 
        if={() => appState$.user.get()} 
        else={<button>Login</button>}
      >
        {user => <span>Welcome, {user.name}!</span>}
      </Show>
    </Reactive.header>
  );
}

docs

configuration.md

core-observables.md

helper-functions.md

index.md

persistence.md

react-integration.md

tile.json