Create a reusable MixConfig that bundles common mix() settings for consistent behavior across Cubits
This skill creates a reusable MixConfig that bundles common settings for mix() calls.
Creates a MixConfig object that:
mix() parameters into a reusable configurationAsk the user what settings they commonly use together, such as:
Define a const MixConfig with the desired parameters:
import 'package:bloc_superpowers/bloc_superpowers.dart';
const apiCallConfig = MixConfig(
retry: retry(maxRetries: 3),
checkInternet: checkInternet,
);
Apply it with config: in any mix() call:
class UserCubit extends Cubit<User> {
void loadUser() => mix(
key: this,
config: apiCallConfig, // Apply the config
() async {
final user = await api.getUser();
emit(user);
},
);
}
class ProductCubit extends Cubit<ProductState> {
void loadProducts() => mix(
key: this,
config: apiCallConfig, // Same config, different Cubit
() async {
final products = await api.getProducts();
emit(state.copyWith(products: products));
},
);
}
MixConfig accepts all the same parameters as mix():
const myConfig = MixConfig(
// Feature configurations
retry: retry(...),
checkInternet: checkInternet(...),
nonReentrant: nonReentrant,
throttle: throttle(...),
debounce: debounce(...),
fresh: fresh(...),
sequential: sequential(...),
// Callbacks
before: myBeforeCallback,
after: myAfterCallback,
wrapRun: myWrapRunCallback,
catchError: myErrorHandler,
);
const apiConfig = MixConfig(
retry: retry(maxRetries: 3),
checkInternet: checkInternet,
);
void _logStart() => print('Starting operation...');
void _logEnd() => print('Operation complete');
void _logError(Object error, StackTrace stack) {
print('Error: $error');
}
const apiConfigWithLogging = MixConfig(
retry: retry(maxRetries: 3),
checkInternet: checkInternet,
before: _logStart,
after: _logEnd,
catchError: _logError,
);
const criticalDataConfig = MixConfig(
retry: retry.unlimited,
checkInternet: checkInternet(maxRetryDelay: 1.sec),
);
const backgroundSyncConfig = MixConfig(
checkInternet: checkInternet(abortSilently: true),
nonReentrant: nonReentrant,
);
const rateLimitedConfig = MixConfig(
throttle: throttle(duration: 1.sec),
retry: retry(maxRetries: 2),
);
const searchConfig = MixConfig(
debounce: debounce(duration: 300.millis),
nonReentrant: nonReentrant,
);
Individual mix() calls can override config values:
const apiConfig = MixConfig(
retry: retry(maxRetries: 3),
checkInternet: checkInternet,
);
// Use default retry (3)
void loadUsers() => mix(
key: this,
config: apiConfig,
() async { ... },
);
// Override retry to 5
void loadCriticalData() => mix(
key: this,
config: apiConfig,
retry: retry(maxRetries: 5), // Overrides config's retry
() async { ... },
);
Values are resolved in this order (later wins):
mix() call// Built-in default: retry has maxRetries: 3
// Config: retry(maxRetries: 5)
// Explicit: retry(maxRetries: 10)
mix(
key: this,
config: myConfig, // Uses maxRetries: 5 from config
retry: retry(maxRetries: 10), // Overrides to 10
() async { ... },
);
// lib/config/mix_configs.dart
import 'package:bloc_superpowers/bloc_superpowers.dart';
const apiConfig = MixConfig(
retry: retry(maxRetries: 3),
checkInternet: checkInternet,
);
const backgroundConfig = MixConfig(
checkInternet: checkInternet(abortSilently: true),
nonReentrant: nonReentrant,
);
const searchConfig = MixConfig(
debounce: debounce(duration: 300.millis),
);
// For configs specific to one Cubit
const _orderConfig = MixConfig(
retry: retry(maxRetries: 5),
sequential: sequential,
);
class OrderCubit extends Cubit<OrderState> {
void placeOrder(Order order) => mix(
key: this,
config: _orderConfig,
() async { ... },
);
}
// lib/config/mix_configs.dart
import 'package:bloc_superpowers/bloc_superpowers.dart';
void _logError(Object error, StackTrace stack) {
// Log to your analytics service
analyticsService.logError(error, stack);
}
/// Standard config for all API calls
const apiConfig = MixConfig(
retry: retry(maxRetries: 3),
checkInternet: checkInternet,
catchError: _logError,
);
/// Config for critical startup data
const criticalDataConfig = MixConfig(
retry: retry.unlimited,
checkInternet: checkInternet(maxRetryDelay: 1.sec),
catchError: _logError,
);
/// Config for background operations
const backgroundConfig = MixConfig(
checkInternet: checkInternet(abortSilently: true),
nonReentrant: nonReentrant,
);
/// Config for search operations
const searchConfig = MixConfig(
debounce: debounce(duration: 300.millis),
);
// Usage in Cubit
class UserCubit extends Cubit<UserState> {
void loadUser() => mix(
key: this,
config: apiConfig,
() async {
final user = await api.getUser();
emit(state.copyWith(user: user));
},
);
void loadInitialData() => mix(
key: this,
config: criticalDataConfig,
() async {
final data = await api.getInitialData();
emit(state.copyWith(initialData: data));
},
);
void syncInBackground() => mix(
key: BackgroundSync,
config: backgroundConfig,
() async {
await api.sync();
},
);
void search(String query) => mix(
key: Search,
config: searchConfig,
() async {
final results = await api.search(query);
emit(state.copyWith(searchResults: results));
},
);
}
Ask the user:
npx skills add marcglasberg/create-mix-config下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer