AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Mobx React Form Observers Interceptors

skill-foxhound87-skills-mobx-react-form-observers-interceptors · by foxhound87

MobX observers and interceptors for mobx-react-form — observe field changes, intercept mutations, log changes, reject invalid values, cleanup with disposers.

No reviews yet
0 installs
19 views
0.0% view→install

Install

$ agentstack add skill-foxhound87-skills-mobx-react-form-observers-interceptors

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-foxhound87-skills-mobx-react-form-observers-interceptors)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Mobx React Form Observers Interceptors? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Skill: mobx-react-form-observers-interceptors

Mission

Guide the user through using MobX observers and interceptors in mobx-react-form to react to or intercept field value changes in real time.

Use this skill when the user needs to:

  • Observe field value changes (post-commit)
  • Intercept and potentially reject value changes (pre-commit)
  • Transform values before they are committed
  • Log all field changes in a debug panel
  • Clean up observers/interceptors on unmount

Key Distinction

| Feature | observe() | intercept() | |---------|-----------|-------------| | When | After value change (post-commit) | Before value change (pre-commit) | | Can reject | No (read-only) | Yes (return null) | | Can modify | No | Yes (modify change object) | | Use case | Logging, side effects, reactions | Validation, transformation, rejection |

observe()

Fires after a value has been committed. Read-only — cannot modify or reject.

Field-level observe

form.$('firstName').observe(({ form, field, change }) => {
  console.log(`${field.path} changed: "${change.oldValue}" → "${change.newValue}"`);
});

// Or using shorthand (default key = 'value')
form.$('email').observe(({ change }) => {
  console.log('Email changed to:', change.newValue);
});

Form-level observe (by path)

form.observe({
  path: 'password',
  key: 'value',
  call: ({ form, field, change }) => {
    if (change.newValue.length > 0) {
      form.$('passwordStrength').set(
        change.newValue.length > 8 ? 'strong' : 'weak'
      );
    }
  },
});

Observe other field properties

form.observe({
  path: 'email',
  key: 'focused',    // observe focus changes
  call: ({ change }) => {
    console.log('Email focus:', change.newValue);
  },
});

Observe fields map (additions/removals)

form.observe({
  path: 'members',
  key: 'fields',  // observe the fields map
  call: ({ change }) => {
    console.log('Members changed:', change.type); // "add", "delete", "update"
  },
});

intercept()

Fires before a value change is committed. Can modify or reject.

Field-level intercept

form.$('email').intercept(({ form, field, change }) => {
  // Reject if no @
  if (typeof change.newValue === 'string' && !change.newValue.includes('@')) {
    return null; // reject the change
  }
  return change; // allow the change
});

Form-level intercept (by path)

form.intercept({
  path: 'zipCode',
  key: 'value',
  call: ({ change }) => {
    // Strip non-digits
    change.newValue = String(change.newValue).replace(/\D/g, '');
    return change; // must return the change object
  },
});

Intercept return values

| Return | Behavior | |--------|----------| | change (modified or not) | Allow the mutation | | null | Reject the change entirely |

Using observers / interceptors Props

Define observers/interceptors in the field definition for automatic handling of dynamically added fields:

const observers = {
  'club': [{
    key: 'focused',
    call: ({ form, field, change }) => {
      console.log(`Club focus: ${change.newValue}`);
    },
  }],
  'members[].hobbies[]': [{
    key: 'touched',
    call: ({ form, field, change }) => {
      console.log(`Hobby ${field.path} touched: ${change.newValue}`);
    },
  }],
};

new Form({ fields, observers, interceptors, ... });

Or in unified mode:

const fields = {
  email: {
    observers: [{
      key: 'value',
      call: ({ change }) => console.log('Email:', change.newValue),
    }],
    interceptors: [{
      key: 'value',
      call: ({ change }) => {
        if (typeof change.newValue === 'string' && !change.newValue.includes('@')) {
          return null;
        }
        return change;
      },
    }],
  },
};

Real-World: Change Log Panel

const [logs, setLogs] = useState([]);

useEffect(() => {
  form.each((field) => {
    field.observe(({ change, field }) => {
      const entry = {
        field: field.path,
        from: change.oldValue,
        to: change.newValue,
        time: new Date().toLocaleTimeString(),
      };
      setLogs((prev) => [entry, ...prev].slice(0, 20));
    });
  });
  return () => form.dispose();
}, [form]);

// Render:
{logs.map((log, i) => (
  
    {log.time}
    {log.field}
    : {String(log.from)}
    → {String(log.to)}
  
))}

Real-World: Pre-commit Validation

useEffect(() => {
  form.$('age').intercept(({ change }) => {
    const num = Number(change.newValue);
    if (isNaN(num) || num  150) {
      return null; // reject invalid ages
    }
    return change;
  });
  return () => form.dispose();
}, [form]);

Cleanup with dispose()

Always clean up on unmount to prevent memory leaks:

useEffect(() => {
  // Register observers/interceptors...
  form.$('email').observe(/* ... */);
  form.$('password').intercept(/* ... */);

  return () => form.dispose(); // cleanup all
}, [form]);

Dispose all

form.dispose(); // removes all observers and interceptors recursively

Dispose single event

form.dispose({
  type: 'observer',
  path: 'password',
  key: 'value',
});

// Or on selected field
form.$('password').dispose({
  type: 'interceptor',
  key: 'value',
});

Combining observe() with autorun()

For computed/derived values, combine with MobX autorun():

import { autorun } from 'mobx';

useEffect(() => {
  const disposer = autorun(() => {
    const firstName = form.$('firstName').value;
    const lastName = form.$('lastName').value;
    form.$('fullDisplay').set(`${firstName} ${lastName}`.trim() || '(empty)');
  });

  return () => {
    form.dispose();    // removes observers
    disposer();        // removes autorun
  };
}, [form]);

Key Takeaways

  1. Post-commit (observe): Read-only listeners after value is written — logging, side effects.
  2. Pre-commit (intercept): Can modify or reject values before they're stored.
  3. Always return change: Interceptors must return the change object (possibly modified) or null.
  4. Props-based: Define observers/interceptors in field definitions for dynamic fields.
  5. Dispose on unmount: Always call form.dispose() to clean up all MobX events.
  6. Dual cleanup: form.dispose() for form events, disposer() for raw MobX reactions.

Related Skills

  • [mobx-react-form-api](../mobx-react-form-api/SKILL.md) — Core API prerequisite
  • [mobx-react-form-events](../mobx-react-form-events/SKILL.md) — Event hooks
  • [mobx-react-form-computed](../mobx-react-form-computed/SKILL.md) — autorun and computed props

Source & license

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

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

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.