Dispatch Patterns
Core action dispatching patterns for the Context-Action framework, including execution modes, filtering, and performance optimization.
Import
import { createActionContext, ActionPayloadMap } from '@context-action/react';Prerequisites
For complete setup instructions including type definitions, context creation, and provider configuration, see Basic Action Setup.
This document uses the AppActions pattern from the setup guide:
- Type definitions → Extended Action Interface
- Context creation → Single Domain Context
- Provider setup → Single Provider Setup
The examples assume you have configured the following context:
interface AppActions extends ActionPayloadMap {
updateUser: { id: string; name: string; email: string };
processOrder: { orderId: string; items: any[]; total: number };
broadcastEvent: { event: string; data: any };
fastestResponse: { query: string };
sensitiveOperation: { token: string; data: any };
dynamicAction: { type: string; payload: any };
slowOperation: { complexData: any };
criticalAction: { priority: number; data: any };
riskyAction: { operation: string };
bestEffortAction: { data: any };
}
const {
Provider: AppActionProvider,
useActionDispatch: useAppDispatch,
useActionHandler: useAppHandler,
useActionRegister: useAppRegister
} = createActionContext<AppActions>('App');Basic Dispatch
Simple action dispatching without result collection.
function UserComponent() {
const dispatch = useAppDispatch();
const handleUserUpdate = async () => {
// Basic action dispatch
await dispatch('updateUser', { id: '123', name: 'John', email: 'john@example.com' });
};
const handleOrderProcess = async (orderData) => {
// Dispatch with execution options
await dispatch('processOrder', orderData, {
executionMode: 'parallel',
timeout: 5000
});
};
return (
<div>
<button onClick={handleUserUpdate}>Update User</button>
<button onClick={() => handleOrderProcess(orderData)}>Process Order</button>
</div>
);
}Execution Modes
Control how multiple handlers for the same action are executed.
Sequential Execution (Default)
function OrderComponent() {
const dispatch = useAppDispatch();
const handleProcessOrder = async (orderData) => {
// Handlers execute one after another in priority order
await dispatch('processOrder', orderData, {
executionMode: 'sequential'
});
};
return <button onClick={() => handleProcessOrder(orderData)}>Process Order</button>;
}Handlers execute in sequence, allowing early handlers to modify payload for later ones.
Parallel Execution
function EventComponent() {
const dispatch = useAppDispatch();
const handleBroadcast = async (eventData) => {
// All handlers execute simultaneously
await dispatch('broadcastEvent', eventData, {
executionMode: 'parallel'
});
};
return <button onClick={() => handleBroadcast(eventData)}>Broadcast Event</button>;
}Best for independent operations like analytics, logging, and notifications.
When result collection is enabled, results are assembled in the registered priority order after all parallel handlers settle. Completion timing affects when side effects finish, but does not change the meaning of first, last, or all result strategies.
Race Execution
function SearchComponent() {
const dispatch = useAppDispatch();
const handleFastSearch = async (queryData) => {
// First completed handler wins
await dispatch('fastestResponse', queryData, {
executionMode: 'race'
});
};
return <button onClick={() => handleFastSearch(queryData)}>Fast Search</button>;
}Useful for fallback mechanisms and performance-critical operations.
Handler Filtering
Fine-grained control over which handlers execute.
Tag-Based Filtering
function UserManagementComponent() {
const dispatch = useAppDispatch();
const handleUserUpdate = async (payload) => {
await dispatch('updateUser', payload, {
filter: {
handlerIds: ['validator', 'business-logic'],
excludeHandlerIds: ['analytics', 'logging']
}
});
};
return <button onClick={() => handleUserUpdate(userData)}>Update User</button>;
}Handler ID Filtering
function SecurityComponent() {
const dispatch = useAppDispatch();
const handleSensitiveOperation = async (data) => {
// Only execute security-related handlers
await dispatch('sensitiveOperation', data, {
filter: {
handlerIds: ['security-check'],
excludeHandlerIds: ['analytics']
}
});
};
return <button onClick={() => handleSensitiveOperation(secureData)}>Secure Operation</button>;
}Custom Handler Filtering
function DynamicActionComponent() {
const dispatch = useAppDispatch();
const handleDynamicAction = async (payload) => {
await dispatch('dynamicAction', payload, {
filter: {
custom: (config) => {
// Complex filtering logic
return config.priority > 50 &&
!config.id?.includes('optional');
}
}
});
};
return <button onClick={() => handleDynamicAction(dynamicData)}>Dynamic Action</button>;
}Performance Optimization
Timeout Control
function SlowOperationComponent() {
const dispatch = useAppDispatch();
const handleSlowOperation = async (data) => {
// Set timeout for action execution
await dispatch('slowOperation', data, {
timeout: 10000 // 10 second timeout
});
};
return <button onClick={() => handleSlowOperation(complexData)}>Start Slow Operation</button>;
}Priority-Based Execution
function CriticalActionComponent() {
const dispatch = useAppDispatch();
const handleCriticalAction = async (payload) => {
// Execute only high-priority handlers
await dispatch('criticalAction', payload, {
filter: {
custom: (config) => config.priority >= 80
}
});
};
return <button onClick={() => handleCriticalAction(criticalData)}>Critical Action</button>;
}Error Handling
Basic Error Handling
function RiskyActionComponent() {
const dispatch = useAppDispatch();
const handleRiskyAction = async (payload) => {
try {
await dispatch('riskyAction', payload);
} catch (error) {
console.error('Action failed:', error);
}
};
return <button onClick={() => handleRiskyAction(riskyData)}>Risky Action</button>;
}Silent Failures
function BestEffortComponent() {
const register = useAppRegister();
const handleBestEffortAction = async (payload) => {
// Use dispatchWithResult when callers need per-handler failure details.
const result = await register.dispatchWithResult('bestEffortAction', payload, {
result: { collect: true }
});
if (result.outcome === 'completed_with_errors') {
console.error('Some handlers failed:', result.errors);
}
};
return <button onClick={() => handleBestEffortAction(effortData)}>Best Effort Action</button>;
}Real-World Examples
- Search Page - Debounced search with filtering
- Scroll Page - Performance-optimized scroll handling
- Priority Demo - Priority-based execution patterns
Related Patterns
- Action Basic Usage - Fundamental action patterns
- Dispatch with Result - Result collection patterns
- Register Patterns - Handler registration patterns
- Type System - TypeScript integration
- Basic Action Setup - Setup patterns and type definitions