Storybook's core preview API providing hooks, decorators, story composition utilities, and simulation tools for building UI components in isolation
—
React-like hooks for state management, lifecycle methods, and communication within the Storybook preview environment. These hooks enable interactive stories, custom addon development, and advanced story behavior.
Core hooks for managing story arguments and global state.
/**
* Returns current story args, update function, and reset function
* @returns Array containing [args, updateArgs, resetArgs]
*/
function useArgs<TArgs>(): [
TArgs,
(newArgs: Partial<TArgs>) => void,
(argNames?: (keyof TArgs)[]) => void
];
/**
* Returns current global args and update function
* @returns Array containing [globals, updateGlobals]
*/
function useGlobals(): [Args, (newGlobals: Args) => void];
/**
* Returns the current story context with metadata
* @returns Complete story context object
*/
function useStoryContext<TRenderer>(): StoryContext<TRenderer>;
/**
* Retrieves parameter value for the current story
* @param parameterKey - Key of the parameter to retrieve
* @param defaultValue - Default value if parameter is not found
* @returns Parameter value or default
*/
function useParameter<S>(parameterKey: string, defaultValue?: S): S | undefined;Usage Examples:
import { useArgs, useGlobals, useParameter } from "@storybook/preview-api";
export const InteractiveDecorator = (Story, context) => {
const [args, updateArgs, resetArgs] = useArgs();
const [globals, updateGlobals] = useGlobals();
const theme = useParameter('theme', 'light');
const handleClick = () => {
updateArgs({ clicked: true });
updateGlobals({ ...globals, lastAction: 'click' });
};
return (
<div data-theme={theme}>
<button onClick={handleClick}>Update Args</button>
<button onClick={() => resetArgs(['clicked'])}>Reset</button>
<Story />
</div>
);
};Standard React hook patterns for component lifecycle and state management.
/**
* State management hook similar to React.useState
* @param initialState - Initial state value or function returning initial state
* @returns Array containing [state, setState]
*/
function useState<S>(initialState: (() => S) | S): [S, (update: ((prevState: S) => S) | S) => void];
/**
* Side effects hook similar to React.useEffect
* @param create - Effect function, can return cleanup function
* @param deps - Dependency array for effect re-execution
*/
function useEffect(create: () => (() => void) | void, deps?: any[]): void;
/**
* Memoization hook similar to React.useMemo
* @param nextCreate - Function that returns the memoized value
* @param deps - Dependency array for memoization
* @returns Memoized value
*/
function useMemo<T>(nextCreate: () => T, deps?: any[]): T;
/**
* Callback memoization hook similar to React.useCallback
* @param callback - Function to memoize
* @param deps - Dependency array for memoization
* @returns Memoized callback function
*/
function useCallback<T>(callback: T, deps?: any[]): T;
/**
* Mutable ref object hook similar to React.useRef
* @param initialValue - Initial value for the ref
* @returns Mutable ref object
*/
function useRef<T>(initialValue: T): { current: T };
/**
* Reducer pattern hook similar to React.useReducer
* @param reducer - Reducer function
* @param initialState - Initial state value
* @returns Array containing [state, dispatch]
*/
function useReducer<S, A>(
reducer: (state: S, action: A) => S,
initialState: S
): [S, (action: A) => void];Usage Examples:
export const StatefulDecorator = (Story, context) => {
const [count, setCount] = useState(0);
const [data, setData] = useState([]);
const timerRef = useRef(null);
useEffect(() => {
timerRef.current = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => {
if (timerRef.current) {
clearInterval(timerRef.current);
}
};
}, []);
const memoizedValue = useMemo(() => {
return data.filter(item => item.active).length;
}, [data]);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
<div>
<p>Count: {count}</p>
<p>Active items: {memoizedValue}</p>
<Story />
</div>
);
};Hook for subscribing to Storybook's communication channel events.
/**
* Subscribe to Storybook channel events
* @param eventMap - Object mapping event names to listener functions
* @param deps - Dependency array for re-subscription
* @returns Function to emit events
*/
function useChannel(eventMap: EventMap, deps?: any[]): (eventId: string, ...args: any[]) => void;
interface EventMap {
[eventId: string]: Listener;
}
interface Listener {
(...args: any[]): void;
}Usage Examples:
export const ChannelDecorator = (Story, context) => {
const [messages, setMessages] = useState([]);
const emit = useChannel({
'custom-event': (data) => {
setMessages(prev => [...prev, data]);
},
'reset-messages': () => {
setMessages([]);
}
}, []);
return (
<div>
<button onClick={() => emit('custom-event', { text: 'Hello', timestamp: Date.now() })}>
Send Message
</button>
<ul>
{messages.map((msg, i) => (
<li key={i}>{msg.text} - {msg.timestamp}</li>
))}
</ul>
<Story />
</div>
);
};Core infrastructure for hook state and lifecycle management.
/**
* Core class managing hook state and lifecycle
*/
class HooksContext<TRenderer, TArgs = any> {
constructor(renderContext: RenderContext<TRenderer>);
/**
* Clean hook state and prepare for next render
*/
clean(): void;
/**
* Get current render context
* @returns Current render context
*/
getRenderContext(): RenderContext<TRenderer>;
/**
* Set hook state for current render
* @param index - Hook index
* @param value - Hook state value
*/
setHookState(index: number, value: any): void;
/**
* Get hook state for current render
* @param index - Hook index
* @returns Hook state value
*/
getHookState(index: number): any;
/**
* Reset all hook state
*/
resetHookState(): void;
}
/**
* Decorator applicator with hooks support
* @returns Decorator function that manages hook context
*/
function applyHooks<TRenderer>(): DecoratorFunction<TRenderer>;interface Args {
[key: string]: any;
}
interface StoryContext<TRenderer = any> {
id: string;
name: string;
title: string;
parameters: Parameters;
args: Args;
argTypes: ArgTypes;
globals: Args;
hooks: HooksContext<TRenderer>;
viewMode: 'story' | 'docs';
}
interface RenderContext<TRenderer = any> {
id: string;
title: string;
name: string;
storyContext: StoryContext<TRenderer>;
renderToDOM: Function;
unboundStoryFn: Function;
}Install with Tessl CLI
npx tessl i tessl/npm-storybook--preview-api