# Mobx React Form Multi Step

> Multi-step wizard forms for mobx-react-form — nested groups per step, per-step validation, navigation gating, review screen, final submission.

- **Type:** Skill
- **Install:** `agentstack add skill-foxhound87-skills-mobx-react-form-multi-step`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [foxhound87](https://agentstack.voostack.com/s/foxhound87)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [foxhound87](https://github.com/foxhound87)
- **Source:** https://github.com/foxhound87/skills/tree/main/mobx-react-form-multi-step

## Install

```sh
agentstack add skill-foxhound87-skills-mobx-react-form-multi-step
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Skill: mobx-react-form-multi-step

## Mission

Guide the user through building **multi-step wizard forms** using mobx-react-form with nested field groups, per-step validation, step indicators, and final submission.

Use this skill when the user needs to:
- Build a multi-step registration/checkout wizard
- Validate each step before advancing
- Track completed steps visually
- Show a review screen with all collected data
- Submit all steps together

## Concept

Each step is a **nested field group** (dot-notation) within a single form instance. React state tracks the current step, completed steps, and per-step errors. Step navigation gates progression on validation. The review step shows accumulated data before final submission.

```
Form
├── step1 (group)
│   ├── firstName
│   ├── lastName
│   ├── email
│   └── phone
├── step2 (group)
│   ├── street
│   ├── city
│   ├── zipCode
│   └── country
└── step3 (group)
    ├── username
    ├── password
    └── confirmPassword
```

## Form Setup

### Fields definition (separated mode with dot-notation groups)

```javascript
const fields = [
  'step1.firstName',
  'step1.lastName',
  'step1.email',
  'step1.phone',
  'step2.street',
  'step2.city',
  'step2.zipCode',
  'step2.country',
  'step3.username',
  'step3.password',
  'step3.confirmPassword',
];
```

### Validation rules per field

```javascript
const rules = {
  'step1.firstName': 'required|string|min:2',
  'step1.email': 'required|email',
  'step3.password': 'required|string|min:6',
  'step3.confirmPassword': 'required|string|min:6|same:step3.password',
  // ...
};
```

### Initial values

```javascript
const values = {
  step1: { firstName: 'John', lastName: 'Doe', email: 'john@example.com', phone: '+1 555-1234' },
  step2: { street: '456 Oak Avenue', city: 'San Francisco', zipCode: '94102', country: 'USA' },
  step3: {},
};
```

## Component Walkthrough

### Step definitions

```jsx
const steps = [
  { key: 'step1', label: 'Personal Info', icon: User },
  { key: 'step2', label: 'Address', icon: MapPin },
  { key: 'step3', label: 'Account', icon: Settings },
  { key: 'review', label: 'Review', icon: ClipboardCheck },
];

const stepFields = {
  step1: ['firstName', 'lastName', 'email', 'phone'],
  step2: ['street', 'city', 'zipCode', 'country'],
  step3: ['username', 'password', 'confirmPassword'],
};
```

### State management

```jsx
const [currentStep, setCurrentStep] = useState(0);
const [completedSteps, setCompletedSteps] = useState(new Set());
const [errors, setErrors] = useState({});
```

### Group access

```jsx
const stepGroups = useMemo(() => ({
  0: form.$('step1'),
  1: form.$('step2'),
  2: form.$('step3'),
}), [form]);
```

### Per-step validation

```jsx
const validateStep = useCallback(async (stepIndex) => {
  const group = stepGroups[stepIndex];
  if (!group) return true;
  await group.validate({ showErrors: true });
  const valid = group.isValid;
  if (!valid) {
    setErrors((prev) => ({ ...prev, [stepIndex]: group.errors() }));
  } else {
    setErrors((prev) => { const next = { ...prev }; delete next[stepIndex]; return next; });
  }
  return valid;
}, [stepGroups]);
```

### Navigation

```jsx
const handleNext = useCallback(async () => {
  const valid = await validateStep(currentStep);
  if (!valid) return;
  setCompletedSteps((prev) => new Set([...prev, currentStep]));
  setCurrentStep((prev) => Math.min(prev + 1, steps.length - 1));
}, [currentStep, validateStep]);

const handleBack = useCallback(() => {
  setCurrentStep((prev) => Math.max(prev - 1, 0));
}, []);
```

### Field rendering per step

```jsx
const currentGroup = stepGroups[currentStep];
const currentFields = {};

if (currentGroup) {
  const fieldNames = stepFields[steps[currentStep].key] || [];
  fieldNames.forEach((name) => {
    currentFields[name] = currentGroup.$(name);
  });
}

// Render:

```

### Step indicator

```jsx
{steps.map((s, i) => (
   isCompleted && onGoTo(i)}
    disabled={!isCompleted}
    className={i === currentStep ? 'active' : ''}
  >
    {completedSteps.has(i) ?  : i + 1}
    {s.label}
  
))}
```

### Review screen

```jsx
const step1 = form.$('step1');
const step2 = form.$('step2');
const step3 = form.$('step3');

```

### Final submission

```jsx
const handleSubmit = useCallback(async () => {
  let allValid = true;
  for (let i = 0; i  new Set([...prev, i]));
    if (!valid) allValid = false;
  }
  if (allValid) {
    await form.submit();
    setSubmitted(true);
  }
}, [validateStep, stepGroups, form]);
```

## Handling File Fields in Steps

File fields can be included in any step:

```javascript
const fields = [
  'step1.firstName',
  'step1.avatar',     // file field
  'step2.documents',  // file field
];
```

## Nested Composition Alternative

For completely independent forms (different submit endpoints), see the [mobx-react-form-composer](../mobx-react-form-composer/SKILL.md) pattern instead of a single multi-step form.

## Key Takeaways

1. **Nested groups**: Each step is a dot-notation group (`step1.*`, `step2.*`) in the same form.
2. **Per-step validation**: Use `group.validate()` to validate only the current step.
3. **Gate navigation**: Check `group.isValid` to decide whether to advance.
4. **Track completion**: Use a `Set` of step indices for visual state.
5. **Persist data**: Previous steps' values remain in the form — review step reads them directly.
6. **Final validation**: Re-validate all steps at submission to catch changes from revisiting.

## Related Skills

- [mobx-react-form-api](../mobx-react-form-api/SKILL.md) — Core API prerequisite
- [mobx-react-form-nested](../mobx-react-form-nested/SKILL.md) — Nested fields for step groups
- [mobx-react-form-validation](../mobx-react-form-validation/SKILL.md) — Per-step validation
- [mobx-react-form-composer](../mobx-react-form-composer/SKILL.md) — Alternative: multiple independent forms

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [foxhound87](https://github.com/foxhound87)
- **Source:** [foxhound87/skills](https://github.com/foxhound87/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-foxhound87-skills-mobx-react-form-multi-step
- Seller: https://agentstack.voostack.com/s/foxhound87
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
