asyncredux-state-access
Access store state in widgets using `context.state`, `context.select()`, and `context.read()`. Covers when to use each method, setting up BuildContext extensions, and optimizing widget rebuilds with selective state access.
Best use case
asyncredux-state-access is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Access store state in widgets using `context.state`, `context.select()`, and `context.read()`. Covers when to use each method, setting up BuildContext extensions, and optimizing widget rebuilds with selective state access.
Teams using asyncredux-state-access should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/asyncredux-state-access/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How asyncredux-state-access Compares
| Feature / Agent | asyncredux-state-access | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Access store state in widgets using `context.state`, `context.select()`, and `context.read()`. Covers when to use each method, setting up BuildContext extensions, and optimizing widget rebuilds with selective state access.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
## BuildContext Extension Setup
To access your application state in widgets, first define a `BuildContext` extension. Add this to your project (typically in a shared file that all widgets can import):
```dart
extension BuildContextExtension on BuildContext {
AppState get state => getState<AppState>();
AppState read() => getRead<AppState>();
R select<R>(R Function(AppState state) selector) => getSelect<AppState, R>(selector);
R? event<R>(Evt<R> Function(AppState state) selector) => getEvent<AppState, R>(selector);
}
```
Replace `AppState` with your actual state class name.
## The Three State Access Methods
### context.state
Grants access to the entire state object. All widgets that use `context.state` will automatically rebuild whenever the store state changes (any part of it).
```dart
Widget build(BuildContext context) {
return Text('Counter: ${context.state.counter}');
}
```
### context.select()
Retrieves only specific state portions. This is more efficient as it only rebuilds the widget when the selected part of the state changes.
```dart
Widget build(BuildContext context) {
var counter = context.select((state) => state.counter);
return Text('Counter: $counter');
}
```
### context.read()
Retrieves state without triggering rebuilds. Use this in event handlers, `initState`, or anywhere you need to read state once without subscribing to changes.
```dart
void _onButtonPressed() {
var currentCount = context.read().counter;
print('Current count is $currentCount');
}
```
## When to Use Each Method
| Method | Use In | Triggers Rebuilds? | Best For |
|--------|--------|-------------------|----------|
| `context.state` | `build` method | Yes, on any state change | Simple widgets or when you need many state properties |
| `context.select()` | `build` method | Only when selected part changes | Performance-sensitive widgets |
| `context.read()` | `initState`, event handlers, callbacks | No | One-time reads, button handlers |
## Accessing Multiple State Properties
When you need several pieces of state, you have two options:
**Option 1: Multiple select calls**
```dart
Widget build(BuildContext context) {
var name = context.select((state) => state.user.name);
var email = context.select((state) => state.user.email);
var itemCount = context.select((state) => state.items.length);
// Widget rebuilds only if name, email, or itemCount changes
return Text('$name ($email) - $itemCount items');
}
```
**Option 2: Dart records for combined selection**
```dart
Widget build(BuildContext context) {
var (name, email) = context.select((state) => (state.user.name, state.user.email));
return Text('$name ($email)');
}
```
## Additional Context Methods for Action States
Beyond state access, the context extension provides methods for tracking async action progress:
```dart
Widget build(BuildContext context) {
// Check if an action is currently running
if (context.isWaiting(LoadDataAction)) {
return CircularProgressIndicator();
}
// Check if an action failed
if (context.isFailed(LoadDataAction)) {
var exception = context.exceptionFor(LoadDataAction);
return Text('Error: ${exception?.message}');
}
// Show the data
return Text('Data: ${context.state.data}');
}
```
Available methods:
- `context.isWaiting(ActionType)` - Returns true if the action is in progress
- `context.isFailed(ActionType)` - Returns true if the action recently failed
- `context.exceptionFor(ActionType)` - Gets the exception from a failed action
- `context.clearExceptionFor(ActionType)` - Manually clears the stored exception
## Widget Selectors Pattern
For complex selection logic, create a `WidgetSelect` class to organize reusable selectors:
```dart
class WidgetSelect {
final BuildContext context;
WidgetSelect(this.context);
// Getter shortcuts
List<Item> get items => context.select((state) => state.items);
User get currentUser => context.select((state) => state.user);
// Custom finder methods
Item? findById(int id) => context.select(
(state) => state.items.firstWhereOrNull((item) => item.id == id)
);
List<Item> searchByText(String text) => context.select(
(state) => state.items.where((item) => item.name.contains(text)).toList()
);
}
```
Add it to your BuildContext extension:
```dart
extension BuildContextExtension on BuildContext {
AppState get state => getState<AppState>();
// ... other methods ...
WidgetSelect get selector => WidgetSelect(this);
}
```
Usage in widgets:
```dart
Widget build(BuildContext context) {
var user = context.selector.currentUser;
var item = context.selector.findById(42);
return Text('${user.name}: ${item?.name}');
}
```
## Important Guidelines
### Avoid context.state inside selectors
Never use `context.state` inside your selector functions. This defeats the purpose of selective rebuilding:
```dart
// WRONG - rebuilds on any state change
var items = context.select((state) => context.state.items.where(...));
// CORRECT - only rebuilds when items change
var items = context.select((state) => state.items.where(...));
```
### Never nest context.select calls
Nesting `context.select` causes errors. Always apply selection at the top level:
```dart
// WRONG - will cause errors
var result = context.select((state) =>
context.select((s) => s.items).where(...) // Nested select!
);
// CORRECT
var items = context.select((state) => state.items);
var result = items.where(...);
```
## Debugging Rebuilds
To observe when widgets rebuild (useful for performance debugging), use a `ModelObserver`:
```dart
var store = Store<AppState>(
initialState: AppState.initialState(),
modelObserver: DefaultModelObserver(),
);
```
The `DefaultModelObserver` logs console output showing:
- Whether a rebuild occurred
- Which connector/widget triggered it
- The view model state
Example output:
```
Model D:1 R:1 = Rebuild:true, Connector:MyWidgetConnector, Model:MyViewModel{counter: 5}
```
## References
URLs from the documentation:
- https://asyncredux.com/sitemap.xml
- https://asyncredux.com/flutter/basics/using-the-store-state
- https://asyncredux.com/flutter/miscellaneous/widget-selectors
- https://asyncredux.com/flutter/miscellaneous/observing-rebuilds
- https://asyncredux.com/flutter/miscellaneous/cached-selectors
- https://asyncredux.com/flutter/basics/store
- https://asyncredux.com/flutter/advanced-actions/action-selectors
- https://asyncredux.com/flutter/connector/store-connector
- https://asyncredux.com/flutter/intro
- https://asyncredux.com/flutter/basics/wait-fail-succeedRelated Skills
awesome-copilot-root-accessibility
Expert assistant for web accessibility (WCAG 2.1/2.2), inclusive UX, and a11y testing Use when: the task directly matches accessibility responsibilities within plugin awesome-copilot-root. Do not use when: a more specific framework or task-focused skill is clearly a better match.
asyncredux-wait-fail-succeed
Show loading states and handle action failures in widgets. Covers `isWaiting(ActionType)` for spinners, `isFailed(ActionType)` for error states, `exceptionFor(ActionType)` for error messages, and `clearExceptionFor()` to reset failure states.
asyncredux-wait-condition
Use `waitCondition()` inside actions to pause execution until state meets criteria. Covers waiting for price thresholds, coordinating between actions, and implementing conditional workflows.
asyncredux-user-exceptions
Handle user-facing errors with UserException. Covers throwing UserException from actions, setting up UserExceptionDialog, customizing error dialogs with `onShowUserExceptionDialog`, and using UserExceptionAction for non-interrupting error display.
asyncredux-sync-actions
Creates AsyncRedux (Flutter) synchronous actions that update state immediately by implementing reduce() to return a new state.
asyncredux-streams-timers
Manage Streams and Timers with AsyncRedux. Covers creating actions to start/stop streams, storing stream subscriptions in store props, dispatching actions from stream callbacks, and proper cleanup with disposeProps().
asyncredux-setup
Initialize, setup and configure AsyncRedux in a Flutter app. Use it whenever starting a new AsyncRedux project, or when the user requests.
asyncredux-selectors
Create and cache selectors for efficient state access. Covers writing selector functions, caching with `cache1` and `cache2`, the reselect pattern, and avoiding repeated computations in widgets.
asyncredux-persistence
Implement local state persistence using Persistor. Covers creating a custom Persistor class, implementing `readState()`, `persistDifference()`, `deleteState()`, using LocalPersist helper, throttling saves, and pausing/resuming persistence with app lifecycle.
asyncredux-optimistic-update-mixin
Add the OptimisticUpdate mixin for instant UI feedback before server confirmation. Covers immediate state changes, automatic rollback on failure, and optionally notifying users of rollback.
asyncredux-navigation
Handle navigation through actions using NavigateAction. Covers setting up the navigator key, dispatching NavigateAction for push/pop/replace, and testing navigation in isolation.
asyncredux-events
Use the Event class to interact with Flutter's stateful widgets (TextField, ListView, etc.). Covers creating Event objects in state, consuming events with `context.event()`, scrolling lists, changing text fields, and the event lifecycle.