rn-state-flows
Complex multi-step operations in React Native. Use when implementing flows with multiple async steps, state machine patterns, or debugging flow ordering issues.
Best use case
rn-state-flows is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Complex multi-step operations in React Native. Use when implementing flows with multiple async steps, state machine patterns, or debugging flow ordering issues.
Teams using rn-state-flows 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/rn-state-flows/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How rn-state-flows Compares
| Feature / Agent | rn-state-flows | 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?
Complex multi-step operations in React Native. Use when implementing flows with multiple async steps, state machine patterns, or debugging flow ordering issues.
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
# Complex State Flows
## Problem Statement
Multi-step operations with dependencies between steps are prone to ordering bugs, missing preconditions, and untested edge cases. Even without a formal state machine library, thinking in states and transitions prevents bugs.
---
## Pattern: State Machine Thinking
**Problem:** Complex flows have implicit states that aren't modeled, leading to invalid transitions.
**Example - Retake flow states:**
```
IDLE → LOADING_COMPLETED → ENABLING_RETAKE → CLEARING_ANSWERS → READY → ANSWERING → MERGING → SUBMITTING → COMPLETE
↓
ERROR
```
**Each transition should have:**
1. **Preconditions** - What must be true before this step
2. **Action** - What happens during this step
3. **Postconditions** - What must be true after this step
4. **Error handling** - What to do if this step fails
```typescript
// Document the flow explicitly
/*
* RETAKE FLOW
*
* State: IDLE
* Precondition: assessment exists
* Action: loadCompletedAssessmentAnswers
* Postcondition: completedAssessmentAnswers populated
*
* State: LOADING_COMPLETED
* Precondition: completedAssessmentAnswers loaded
* Action: enableSkillAreaRetake
* Postcondition: skillArea in retakeAreas set
*
* State: ENABLING_RETAKE
* Precondition: skillArea in retakeAreas
* Action: clearSkillAreaAnswers
* Postcondition: existing answers for skillArea removed
*
* ... continue for each state
*/
```
---
## Pattern: Explicit Flow Implementation
**Problem:** Flow logic scattered across multiple functions, hard to verify ordering.
```typescript
// WRONG - implicit flow, easy to miss steps or misordering
async function startRetake(assessmentId: string, skillArea: string) {
loadCompletedAssessmentAnswers(assessmentId); // Missing await!
await enableSkillAreaRetake(skillArea);
await clearSkillAreaAnswers(skillArea);
}
// CORRECT - explicit flow with validation
async function startRetake(assessmentId: string, skillArea: string) {
const flowId = `retake-${Date.now()}`;
logger.info(`[${flowId}] Starting retake flow`, { assessmentId, skillArea });
// Step 1: Load completed answers
await loadCompletedAssessmentAnswers(assessmentId);
const completedAnswers = useStore.getState().completedAssessmentAnswers;
if (Object.keys(completedAnswers).length === 0) {
throw new Error(`[${flowId}] Failed to load completed answers`);
}
logger.debug(`[${flowId}] Loaded ${Object.keys(completedAnswers).length} answers`);
// Step 2: Enable retake for skill area
await enableSkillAreaRetake(skillArea);
const retakeAreas = useStore.getState().retakeAreas;
if (!retakeAreas.has(skillArea)) {
throw new Error(`[${flowId}] Failed to enable retake for ${skillArea}`);
}
logger.debug(`[${flowId}] Enabled retake for ${skillArea}`);
// Step 3: Clear existing answers
await clearSkillAreaAnswers(skillArea);
logger.debug(`[${flowId}] Cleared answers for ${skillArea}`);
logger.info(`[${flowId}] Retake flow completed`);
}
```
---
## Pattern: Flow Object
**Problem:** Long async functions with many steps become unwieldy.
```typescript
interface FlowStep<TContext> {
name: string;
execute: (context: TContext) => Promise<void>;
validate?: (context: TContext) => void; // Postcondition check
}
interface RetakeContext {
assessmentId: string;
skillArea: string;
flowId: string;
}
const retakeSteps: FlowStep<RetakeContext>[] = [
{
name: 'loadCompletedAnswers',
execute: async (ctx) => {
await loadCompletedAssessmentAnswers(ctx.assessmentId);
},
validate: (ctx) => {
const answers = useStore.getState().completedAssessmentAnswers;
if (Object.keys(answers).length === 0) {
throw new Error(`[${ctx.flowId}] No completed answers loaded`);
}
},
},
{
name: 'enableRetake',
execute: async (ctx) => {
await enableSkillAreaRetake(ctx.skillArea);
},
validate: (ctx) => {
const retakeAreas = useStore.getState().retakeAreas;
if (!retakeAreas.has(ctx.skillArea)) {
throw new Error(`[${ctx.flowId}] Retake not enabled for ${ctx.skillArea}`);
}
},
},
{
name: 'clearAnswers',
execute: async (ctx) => {
await clearSkillAreaAnswers(ctx.skillArea);
},
},
];
async function executeFlow<TContext>(
steps: FlowStep<TContext>[],
context: TContext,
flowName: string
) {
const flowId = `${flowName}-${Date.now()}`;
logger.info(`[${flowId}] Starting flow`, context);
for (const step of steps) {
logger.debug(`[${flowId}] Executing: ${step.name}`);
try {
await step.execute(context);
if (step.validate) {
step.validate(context);
}
logger.debug(`[${flowId}] Completed: ${step.name}`);
} catch (error) {
logger.error(`[${flowId}] Failed at: ${step.name}`, { error: error.message });
throw error;
}
}
logger.info(`[${flowId}] Flow completed`);
}
// Usage
await executeFlow(retakeSteps, { assessmentId, skillArea, flowId }, 'retake');
```
---
## Pattern: Flow State Tracking
**Problem:** Components need to know current flow state for UI feedback.
```typescript
type RetakeFlowState =
| { status: 'idle' }
| { status: 'loading'; step: string }
| { status: 'ready' }
| { status: 'answering'; answeredCount: number }
| { status: 'submitting' }
| { status: 'complete' }
| { status: 'error'; message: string; step: string };
const useRetakeStore = create<{
flowState: RetakeFlowState;
setFlowState: (state: RetakeFlowState) => void;
}>((set) => ({
flowState: { status: 'idle' },
setFlowState: (flowState) => set({ flowState }),
}));
async function startRetake(assessmentId: string, skillArea: string) {
const { setFlowState } = useRetakeStore.getState();
try {
setFlowState({ status: 'loading', step: 'loadingAnswers' });
await loadCompletedAssessmentAnswers(assessmentId);
setFlowState({ status: 'loading', step: 'enablingRetake' });
await enableSkillAreaRetake(skillArea);
setFlowState({ status: 'loading', step: 'clearingAnswers' });
await clearSkillAreaAnswers(skillArea);
setFlowState({ status: 'ready' });
} catch (error) {
setFlowState({
status: 'error',
message: error.message,
step: useRetakeStore.getState().flowState.step,
});
}
}
// Component usage
function RetakeScreen() {
const flowState = useRetakeStore((s) => s.flowState);
if (flowState.status === 'loading') {
return <Loading step={flowState.step} />;
}
if (flowState.status === 'error') {
return <Error message={flowState.message} step={flowState.step} />;
}
// ... render based on state
}
```
---
## Pattern: Integration Testing Flows
**Problem:** Unit tests for individual functions don't catch flow-level bugs.
```typescript
describe('Retake Flow', () => {
beforeEach(() => {
useAssessmentStore.getState()._reset();
});
it('persists answers through complete retake flow', async () => {
const assessmentId = 'test-assessment';
const skillArea = 'fundamentals';
const store = useAssessmentStore;
// Setup: Simulate existing completed assessment
store.getState().setCompletedAnswers(assessmentId, mockCompletedAnswers);
// Execute full flow
await store.getState().loadCompletedAssessmentAnswers(assessmentId);
// Verify postcondition
expect(Object.keys(store.getState().completedAssessmentAnswers).length)
.toBeGreaterThan(0);
await store.getState().enableSkillAreaRetake(skillArea);
// Verify postcondition
expect(store.getState().retakeAreas.has(skillArea)).toBe(true);
await store.getState().clearSkillAreaAnswers(skillArea);
// Simulate user answering
await store.getState().saveAnswer('q1', 4);
// THE CRITICAL CHECK - does the answer persist?
expect(store.getState().userAnswers['q1']).toBe(4);
// Complete flow
await store.getState().submitRetake(assessmentId);
// Verify final state
expect(store.getState().flowState.status).toBe('complete');
});
it('handles error at each step', async () => {
// Test error handling at step 1
mockApi.loadAnswers.mockRejectedValueOnce(new Error('Network error'));
await expect(
store.getState().startRetake(assessmentId, skillArea)
).rejects.toThrow('Network error');
expect(store.getState().flowState.status).toBe('error');
expect(store.getState().flowState.step).toBe('loadingAnswers');
});
});
```
---
## Pattern: Flow Documentation
Document complex flows with diagrams for team understanding:
```markdown
## Retake Flow
### Happy Path
```
┌─────────┐ ┌──────────────┐ ┌───────────────┐ ┌───────────────┐
│ Start │────▶│ Load Answers │────▶│ Enable Retake │────▶│ Clear Answers │
└─────────┘ └──────────────┘ └───────────────┘ └───────────────┘
│ │ │
▼ ▼ ▼
Postcondition: Postcondition: Postcondition:
answers.length > 0 retakeAreas.has(x) cleared for area
│
▼
┌──────────┐ ┌─────────┐ ┌───────────────┐ ┌──────────────────┐
│ Complete │◀────│ Merge │◀────│ User Answers │◀────│ Ready for Input │
└──────────┘ └─────────┘ └───────────────┘ └──────────────────┘
```
### Error States
Any step can fail → transition to ERROR state with step context.
From ERROR: user can retry (back to IDLE) or exit.
```
---
## Checklist: Designing Complex Flows
Before implementing:
- [ ] Sketch state diagram (even on paper)
- [ ] Identify all states, including error states
- [ ] Document preconditions for each transition
- [ ] Document postconditions to verify
- [ ] Plan how to surface state to UI
During implementation:
- [ ] Verify preconditions before each step
- [ ] Validate postconditions after each step
- [ ] Log state transitions with flow ID
- [ ] Handle errors at each step with context
- [ ] Surface flow state for UI feedback
After implementation:
- [ ] Integration test for happy path
- [ ] Integration test for error at each step
- [ ] Verify logs are sufficient for debugging
- [ ] Document flow for team
---
## When to Use XState
Consider XState when:
- Flow has > 6 states
- Complex branching/parallel states
- Need visualization/debugging tools
- State machine is shared across team
For simpler flows, explicit steps with validation (as shown above) are often sufficient and more readable.Related Skills
terraform-state-manager
Terraform State Manager - Auto-activating skill for DevOps Advanced. Triggers on: terraform state manager, terraform state manager Part of the DevOps Advanced skill category.
mermaid-state-diagram-creator
Mermaid State Diagram Creator - Auto-activating skill for Visual Content. Triggers on: mermaid state diagram creator, mermaid state diagram creator Part of the Visual Content skill category.
building-gitops-workflows
This skill enables Claude to construct GitOps workflows using ArgoCD and Flux. It is designed to generate production-ready configurations, implement best practices, and ensure a security-first approach for Kubernetes deployments. Use this skill when the user explicitly requests "GitOps workflow", "ArgoCD", "Flux", or asks for help with setting up a continuous delivery pipeline using GitOps principles. The skill will generate the necessary configuration files and setup code based on the user's specific requirements and infrastructure.
cursor-composer-workflows
Master Cursor Composer for multi-file AI editing, scaffolding, and refactoring. Triggers on "cursor composer", "multi-file edit", "cursor generate files", "composer workflow", "cursor scaffold", "Cmd+I".
flowstudio-power-automate-mcp
Connect to and operate Power Automate cloud flows via a FlowStudio MCP server. Use when asked to: list flows, read a flow definition, check run history, inspect action outputs, resubmit a run, cancel a running flow, view connections, get a trigger URL, validate a definition, monitor flow health, or any task that requires talking to the Power Automate API through an MCP tool. Also use for Power Platform environment discovery and connection management. Requires a FlowStudio MCP subscription or compatible server — see https://mcp.flowstudio.app
flowstudio-power-automate-debug
Debug failing Power Automate cloud flows using the FlowStudio MCP server. Load this skill when asked to: debug a flow, investigate a failed run, why is this flow failing, inspect action outputs, find the root cause of a flow error, fix a broken Power Automate flow, diagnose a timeout, trace a DynamicOperationRequestFailure, check connector auth errors, read error details from a run, or troubleshoot expression failures. Requires a FlowStudio MCP subscription — see https://mcp.flowstudio.app
flowstudio-power-automate-build
Build, scaffold, and deploy Power Automate cloud flows using the FlowStudio MCP server. Load this skill when asked to: create a flow, build a new flow, deploy a flow definition, scaffold a Power Automate workflow, construct a flow JSON, update an existing flow's actions, patch a flow definition, add actions to a flow, wire up connections, or generate a workflow definition from scratch. Requires a FlowStudio MCP subscription — see https://mcp.flowstudio.app
tdd-workflows-tdd-refactor
Use when working with tdd workflows tdd refactor
tdd-workflows-tdd-red
Generate failing tests for the TDD red phase to define expected behavior and edge cases.
tdd-workflows-tdd-green
Implement the minimal code needed to make failing tests pass in the TDD green phase.
tdd-workflows-tdd-cycle
Use when working with tdd workflows tdd cycle
git-pr-workflows-pr-enhance
You are a PR optimization expert specializing in creating high-quality pull requests that facilitate efficient code reviews. Generate comprehensive PR descriptions, automate review processes, and ensu