API Reference
Complete API reference for @xndrjs/adapter-react.
useReactiveValue
Subscribe to a StatePort and return its current value. The component re-renders when the value changes.
Function Signature
function useReactiveValue<T>(reactiveValue: StatePort<T>): T;
Type Parameters:
T- The type of the value
Parameters:
reactiveValue: StatePort<T>- The StatePort to subscribe to (can beReactiveValue,ComputedValue, or anyStatePort)
Returns: The current value of type T
Behavior:
- Automatically detects
ComputedValueand uses shallow equality to prevent infinite loops - Uses React's
useSyncExternalStorefor regularStatePort(efficient) - Uses internal state management for
ComputedValueto handle object equality correctly - Re-renders component when the value changes
Example:
import { useReactiveValue } from '@xndrjs/adapter-react';
import { ReactiveValue, createComputed } from '@xndrjs/core';
function Counter() {
const count = new ReactiveValue(0);
const doubled = createComputed(count)
.as((c) => c * 2)
.for({ [Symbol.dispose]() {} });
const countValue = useReactiveValue(count); // number
const doubledValue = useReactiveValue(doubled); // number
return (
<div>
<p>Count: {countValue}</p>
<p>Doubled: {doubledValue}</p>
</div>
);
}
useStatePort
Convert React useState to a StatePort. Returns a stable StatePort object that doesn't change reference.
Function Signature
function useStatePort<T>(
value: T,
setValue: Dispatch<SetStateAction<T>>,
): StatePort<T>;
Type Parameters:
T- The type of the value
Parameters:
value: T- The current state value (fromuseState)setValue: Dispatch<SetStateAction<T>>- The state setter function (fromuseState)
Returns: A stable StatePort<T> object
Behavior:
- Returns a stable reference (doesn't change on re-renders)
- The port remains reactive:
subscribe()notifies when value changes get()always returns the current value via internal ref- Can be used in
useRef/useMemodependencies without causing re-renders
Example:
import { useState } from 'react';
import { useStatePort } from '@xndrjs/adapter-react';
import { createComputed } from '@xndrjs/core';
function TodoApp() {
const [todos, setTodos] = useState<Todo[]>([]);
const todosPort = useStatePort(todos, setTodos);
// Use the port with computed values or other StatePort operations
const todoCount = createComputed(todosPort)
.as((todos) => todos.length)
.for({ [Symbol.dispose]() {} });
return <div>{/* ... */}</div>;
}
useCreateStatePort
Create a StatePort managed by React state. Returns a stable StatePort object.
Function Signature
function useCreateStatePort<T>(initialValue: T): StatePort<T>;
Type Parameters:
T- The type of the value
Parameters:
initialValue: T- The initial value
Returns: A stable StatePort<T> object
Behavior:
- Returns a stable reference (doesn't change on re-renders)
- Uses React
useStateinternally - The port remains reactive:
subscribe()notifies when value changes - Can be used with computed values and other
StatePortoperations
Example:
import { useCreateStatePort, useReactiveValue } from '@xndrjs/adapter-react';
import { createComputed } from '@xndrjs/core';
function TodoApp() {
const todosPort = useCreateStatePort<Todo[]>([]);
const todos = useReactiveValue(todosPort);
const todoCount = createComputed(todosPort)
.as((todos) => todos.length)
.for({ [Symbol.dispose]() {} });
const addTodo = (todo: Todo) => {
todosPort.set((prev) => [...prev, todo]);
};
return (
<div>
<p>Total: {todos.length}</p>
{/* ... */}
</div>
);
}
useFSM
Automatically initialize an FSM context manager when the component mounts.
Function Signature
function useFSM<TConfig extends Record<PropertyKey, unknown>>(
fsm: FSMContextManager<TConfig, any> | null | undefined,
): void;
Type Parameters:
TConfig- The FSM configuration type
Parameters:
fsm: FSMContextManager<TConfig, any> | null | undefined- The FSM context manager to initialize
Returns: void
Behavior:
- Calls
fsm.initialize()when component mounts initialize()is idempotent, so this hook can be safely used with shared FSM instances- No-op if
fsmisnullorundefined
Example:
import { useFSM } from '@xndrjs/adapter-react';
import { FSMContextManager } from '@xndrjs/fsm';
import { useMemo } from 'react';
function Stopwatch() {
const fsm = useMemo(() => new StopwatchFSM(currentStatePort), []);
// Automatically initialize the FSM
useFSM(fsm);
// Component is reactive to machine state changes
const currentState = useReactiveValue(fsm.currentState);
return <div>Current state: {currentState.name}</div>;
}
useStableReference
Get a stable reference to a value. Returns the same reference across re-renders if the value hasn't changed.
Function Signature
function useStableReference<T>(value: T): T;
Type Parameters:
T- The type of the value
Parameters:
value: T- The value to create a stable reference for
Returns: A stable reference to the value (same reference if value hasn't changed)
Behavior:
- Returns the same reference across re-renders if the value is equal (using
Object.is) - Useful for preventing unnecessary re-renders in child components
- Useful for
useMemo/useCallbackdependencies
Example:
import { useStableReference } from '@xndrjs/adapter-react';
function Parent({ config }) {
const stableConfig = useStableReference(config);
// Child won't re-render if config object reference changed but values are the same
return <Child config={stableConfig} />;
}
Type Exports
All React adapter types are exported for TypeScript usage:
// All hooks are exported with their types
export { useReactiveValue, useStatePort, useCreateStatePort, useFSM, useStableReference };
Next Steps
- Learn about Core concepts
- Explore FSM pattern
- Check out Getting Started