<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cla</title>
    <description>The latest articles on DEV Community by Cla (@foxhound87).</description>
    <link>https://dev.to/foxhound87</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36179%2Fbeffc76d-ce8f-4889-875f-00826392f3ec.jpg</url>
      <title>DEV Community: Cla</title>
      <link>https://dev.to/foxhound87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/foxhound87"/>
    <language>en</language>
    <item>
      <title>mobx-react-form is now mobx-formkit</title>
      <dc:creator>Cla</dc:creator>
      <pubDate>Sun, 16 Aug 2026 11:05:00 +0000</pubDate>
      <link>https://dev.to/foxhound87/mobx-react-form-is-now-mobx-formkit-4kfm</link>
      <guid>https://dev.to/foxhound87/mobx-react-form-is-now-mobx-formkit-4kfm</guid>
      <description>&lt;p&gt;The &lt;code&gt;mobx-react-form&lt;/code&gt; package — after 273 releases ending with &lt;code&gt;7.1.0&lt;/code&gt; — is&lt;br&gt;
now published on npm as &lt;strong&gt;&lt;code&gt;mobx-formkit&lt;/code&gt;&lt;/strong&gt;. The old package name is marked as&lt;br&gt;
&lt;strong&gt;deprecated&lt;/strong&gt; on the npm registry: anyone installing &lt;code&gt;mobx-react-form&lt;/code&gt; today&lt;br&gt;
gets a deprecation notice pointing to &lt;code&gt;mobx-formkit&lt;/code&gt;, with no breaking change&lt;br&gt;
for existing installs already pinned to the old name.&lt;/p&gt;

&lt;p&gt;The new package is a fresh &lt;code&gt;1.0.0&lt;/code&gt; release on top of the exact same codebase&lt;br&gt;
(&lt;code&gt;7.1.0&lt;/code&gt; API), under a name that matches what the library actually is:&lt;br&gt;
&lt;strong&gt;MobX form state management&lt;/strong&gt;, not a React-only project. The GitHub repo,&lt;br&gt;
the demo app and the documentation moved along:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;npm install&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm i mobx-react-form&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm i mobx-formkit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;import (CJS / ESM)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;import MobxReactForm from 'mobx-react-form'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;import MobxFormkit from 'mobx-formkit'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UMD globals&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MobxReactForm&lt;/code&gt;, &lt;code&gt;MobxReactFormValidator*&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MobxFormkit&lt;/code&gt;, &lt;code&gt;MobxFormkitValidator*&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;foxhound87.github.io/mobx-react-form&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;foxhound87.github.io/mobx-formkit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live demo&lt;/td&gt;
&lt;td&gt;old URL → 404&lt;/td&gt;
&lt;td&gt;&lt;code&gt;foxhound87.github.io/mobx-formkit-demo&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repo&lt;/td&gt;
&lt;td&gt;&lt;code&gt;foxhound87/mobx-react-form&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;foxhound87/mobx-formkit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;APIs are identical.&lt;/strong&gt; The only breaking surface is UMD: bundle filenames and&lt;br&gt;
script-tag globals changed from &lt;code&gt;MobxReactForm*&lt;/code&gt; to &lt;code&gt;MobxFormkit*&lt;/code&gt; — update&lt;br&gt;
your &lt;code&gt;&amp;lt;script src&amp;gt;&lt;/code&gt; paths and global references. npm imports and ESM&lt;br&gt;
consumers are unaffected beyond the package name. Old docs URLs under&lt;br&gt;
&lt;code&gt;/mobx-react-form/&lt;/code&gt; now return 404.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why the rebrand — the library, not the framework
&lt;/h2&gt;

&lt;p&gt;The core of the library depends only on &lt;strong&gt;MobX&lt;/strong&gt; (plus &lt;code&gt;lodash-es&lt;/code&gt;) and knows&lt;br&gt;
nothing about React, Vue or any DOM. Form state — values, errors, dirty and&lt;br&gt;
touched flags, validation — lives in observable &lt;code&gt;Form&lt;/code&gt; / &lt;code&gt;Field&lt;/code&gt; instances,&lt;br&gt;
so any reactive consumer can render it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt; (official): &lt;code&gt;mobx-react&lt;/code&gt; / &lt;code&gt;mobx-react-lite&lt;/code&gt; with &lt;code&gt;observer()&lt;/code&gt;;
field props map to component props via the bundled &lt;code&gt;Bindings&lt;/code&gt; (key
rewriters or function-based templates): Material UI, Ant Design, React
Aria, Headless UI, React Select, React Widgets, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vue 3&lt;/strong&gt;: &lt;code&gt;mobx-vue-lite&lt;/code&gt; (&lt;code&gt;&amp;lt;Observer&amp;gt;&lt;/code&gt;, Composition API).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lit&lt;/strong&gt;: &lt;code&gt;@adobe/lit-mobx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular&lt;/strong&gt;: &lt;code&gt;mobx-angular&lt;/code&gt; (&lt;code&gt;*mobxAutorun&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solid&lt;/strong&gt;: &lt;code&gt;mobx-solid&lt;/code&gt; (community). &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Octane&lt;/strong&gt;: &lt;code&gt;@octanejs/mobx&lt;/code&gt;
(mobx-react-lite compatible surface).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vanilla JS&lt;/strong&gt;: plain &lt;code&gt;autorun&lt;/code&gt; / &lt;code&gt;reaction&lt;/code&gt; — no framework at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: the library is &lt;strong&gt;UI-agnostic and not opinionated about React&lt;/strong&gt;.&lt;br&gt;
The package splits into a compact core plus separate subpaths — validators&lt;br&gt;
(&lt;code&gt;mobx-formkit/validators/*&lt;/code&gt;, &lt;code&gt;mobx-formkit/lib/validators/*&lt;/code&gt;), a &lt;code&gt;composer&lt;/code&gt;&lt;br&gt;
for multi-form wizards — plus a dedicated devtools package. Form state lives&lt;br&gt;
in pure MobX; bindings live wherever your UI does.&lt;/p&gt;
&lt;h2&gt;
  
  
  Validation in 2026
&lt;/h2&gt;

&lt;p&gt;Eight validation drivers share one uniform lifecycle — define fields once,&lt;br&gt;
swap or combine plugins without touching field definitions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Driver&lt;/th&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VJF&lt;/td&gt;
&lt;td&gt;vanilla functions&lt;/td&gt;
&lt;td&gt;sync + async&lt;/td&gt;
&lt;td&gt;rules as plain functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DVR&lt;/td&gt;
&lt;td&gt;validatorjs&lt;/td&gt;
&lt;td&gt;sync + async&lt;/td&gt;
&lt;td&gt;declarative rules string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AJV&lt;/td&gt;
&lt;td&gt;ajv&lt;/td&gt;
&lt;td&gt;sync + async&lt;/td&gt;
&lt;td&gt;JSON Schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YUP&lt;/td&gt;
&lt;td&gt;yup&lt;/td&gt;
&lt;td&gt;sync + async&lt;/td&gt;
&lt;td&gt;promise-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JOI&lt;/td&gt;
&lt;td&gt;joi&lt;/td&gt;
&lt;td&gt;sync&lt;/td&gt;
&lt;td&gt;schema objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZOD&lt;/td&gt;
&lt;td&gt;zod&lt;/td&gt;
&lt;td&gt;sync&lt;/td&gt;
&lt;td&gt;zod v3.25+ &lt;strong&gt;and v4&lt;/strong&gt;; use &lt;code&gt;zod/v4/core&lt;/code&gt; for smaller bundles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VALIBOT&lt;/td&gt;
&lt;td&gt;valibot&lt;/td&gt;
&lt;td&gt;sync&lt;/td&gt;
&lt;td&gt;new in 7.1.0 — no &lt;code&gt;package&lt;/code&gt; prop needed, errors per-path incl. nested/array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VINEJS&lt;/td&gt;
&lt;td&gt;@vinejs/vine&lt;/td&gt;
&lt;td&gt;async&lt;/td&gt;
&lt;td&gt;new in 7.1.0 — promise-based, requires a Vine instance + schema&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notable additions of the final &lt;code&gt;7.1.0&lt;/code&gt; cycle: &lt;strong&gt;VALIBOT&lt;/strong&gt; is zero-config&lt;br&gt;
(&lt;code&gt;valibot({ schema })&lt;/code&gt; — no external package prop) and reports per-field&lt;br&gt;
errors for nested and array paths automatically; &lt;strong&gt;VINEJS&lt;/strong&gt; is async by&lt;br&gt;
design (&lt;code&gt;await form.validate()&lt;/code&gt;) and maps &lt;code&gt;error.messages&lt;/code&gt; dot-notated paths&lt;br&gt;
onto the right fields. All drivers support the &lt;code&gt;extend&lt;/code&gt; callback&lt;br&gt;
(&lt;code&gt;{ validator, form }&lt;/code&gt;), and both contracts — sync &lt;code&gt;validateSync&lt;/code&gt; and async&lt;br&gt;
&lt;code&gt;validate&lt;/code&gt; / &lt;code&gt;submit&lt;/code&gt; promises — are intact. Core &lt;code&gt;Form&lt;/code&gt; / &lt;code&gt;Field&lt;/code&gt; methods&lt;br&gt;
(&lt;code&gt;validate&lt;/code&gt;, &lt;code&gt;validateSync&lt;/code&gt;, &lt;code&gt;clear&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt;, &lt;code&gt;$form&lt;/code&gt;, ...) are unchanged.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;valibot&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobx-formkit/lib/validators/VALIBOT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;vinejs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobx-formkit/lib/validators/VINEJS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;vine&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vinejs/vine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;valibot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;valibot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;valibot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;vinejs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vinejs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The library ships 1611 unit/integration tests passing, with 95.89% statement&lt;br&gt;
coverage (86.69% branches), built on TypeScript &lt;code&gt;^5.9&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration path
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install&lt;/strong&gt;: &lt;code&gt;npm i mobx-formkit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap imports&lt;/strong&gt;: replace every &lt;code&gt;mobx-react-form&lt;/code&gt; import and require with
&lt;code&gt;mobx-formkit&lt;/code&gt;. That's it for npm-based consumers — APIs are identical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UMD consumers&lt;/strong&gt;: update bundle filenames and globals from
&lt;code&gt;MobxReactForm*&lt;/code&gt; to &lt;code&gt;MobxFormkit*&lt;/code&gt; (this is the one breaking change).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bookmark the new docs&lt;/strong&gt; (old URLs 404) and check the migration guide in
the documentation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/mobx-formkit" rel="noopener noreferrer"&gt;mobx-formkit&lt;/a&gt; -
&lt;a href="https://www.npmjs.com/package/mobx-react-form" rel="noopener noreferrer"&gt;mobx-react-form (deprecated)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/foxhound87/mobx-formkit" rel="noopener noreferrer"&gt;foxhound87/mobx-formkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://foxhound87.github.io/mobx-formkit/" rel="noopener noreferrer"&gt;https://foxhound87.github.io/mobx-formkit/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live demo: &lt;a href="https://foxhound87.github.io/mobx-formkit-demo/" rel="noopener noreferrer"&gt;https://foxhound87.github.io/mobx-formkit-demo/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;DevTools: &lt;a href="https://github.com/foxhound87/mobx-formkit-devtools" rel="noopener noreferrer"&gt;foxhound87/mobx-formkit-devtools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Community: &lt;a href="https://discord.gg/CVV8w4zat4" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>react</category>
      <category>software</category>
    </item>
    <item>
      <title>The Agentic Skills of mobx-formkit: How AI Assistants Now Master React Forms</title>
      <dc:creator>Cla</dc:creator>
      <pubDate>Tue, 04 Aug 2026 12:34:00 +0000</pubDate>
      <link>https://dev.to/foxhound87/the-agentic-skills-of-mobx-react-form-how-ai-assistants-now-master-react-forms-58mo</link>
      <guid>https://dev.to/foxhound87/the-agentic-skills-of-mobx-react-form-how-ai-assistants-now-master-react-forms-58mo</guid>
      <description>&lt;p&gt;Form handling in React has always been a manual, repetitive, and error-prone affair. For years, &lt;code&gt;mobx-react-form&lt;/code&gt; has solved the runtime side of that problem — reactive form state, validation, bindings — with a clean, declarative API. But 2025 changed what "solving a problem" means: AI coding assistants now write large chunks of our forms for us. The quality of that generated code, however, depends entirely on the quality of the context the model is given.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;agentic skills&lt;/strong&gt;: packaged, installable instruction sets that teach AI assistants the precise idioms, APIs, and patterns of a library before they write a single line of code. The &lt;code&gt;foxhound87/skills&lt;/code&gt; repository brings this to &lt;code&gt;mobx-formkit&lt;/code&gt; — the successor of &lt;code&gt;mobx-react-form&lt;/code&gt; — with a curated collection of 15 specialized skills, one for every major area of the library.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Agent Skills?
&lt;/h2&gt;

&lt;p&gt;Agent skills are essentially prompt-level documentation that lives on the agent's side. They contain the kind of knowledge a senior developer has internalized: exact method signatures, edge cases, the &lt;em&gt;right&lt;/em&gt; pattern versus the &lt;em&gt;working&lt;/em&gt; pattern. When an AI assistant is asked to build a multi-step form or wire up async validation, it doesn't have to guess — it loads the relevant skill and follows battle-tested guidance.&lt;/p&gt;

&lt;p&gt;Skills for &lt;code&gt;mobx-formkit&lt;/code&gt; are distributed via &lt;a href="https://skills.sh" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt; and can be installed in seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the full collection&lt;/span&gt;
npx skills add https://github.com/foxhound87/skills &lt;span class="nt"&gt;--all&lt;/span&gt;

&lt;span class="c"&gt;# Install a single skill&lt;/span&gt;
npx skills add https://github.com/foxhound87/skills &lt;span class="nt"&gt;--skill&lt;/span&gt; mobx-formkit-validation

&lt;span class="c"&gt;# Install for a specific agent (e.g. opencode)&lt;/span&gt;
npx skills add https://github.com/foxhound87/skills &lt;span class="nt"&gt;-a&lt;/span&gt; opencode &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Skill Collection: From Core to Advanced
&lt;/h2&gt;

&lt;p&gt;The 15 skills mirror the mental model of the library itself: a core API layer, a set of field-definition skills, validation, and then a cluster of advanced capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Skills
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches the agent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-api" rel="noopener noreferrer"&gt;mobx-formkit-api&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Installation, &lt;code&gt;Form&lt;/code&gt;/&lt;code&gt;Field&lt;/code&gt; constructor, full property and method reference, helpers, event handlers. The prerequisite for everything else.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-flat" rel="noopener noreferrer"&gt;mobx-formkit-flat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Flat field definitions — unified, separated, and mixed modes, field properties, patterns.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-nested" rel="noopener noreferrer"&gt;mobx-formkit-nested&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Nested and array fields — dot notation, array notation, dynamic add/remove, &lt;code&gt;ArrayMap&lt;/code&gt;, field traversal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-validation" rel="noopener noreferrer"&gt;mobx-formkit-validation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;All six validation plugins (DVR, VJF, SVK, YUP, JOI, ZOD), async and cross-field validation, validation hooks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-bindings" rel="noopener noreferrer"&gt;mobx-formkit-bindings&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Field bindings — default rewriter/template, custom bindings, &lt;code&gt;$try&lt;/code&gt;, per-field mapping, UI framework adapters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-multi-step" rel="noopener noreferrer"&gt;mobx-formkit-multi-step&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Multi-step wizard forms — nested groups, per-step validation, navigation, review screens.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Advanced Skills
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches the agent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-events" rel="noopener noreferrer"&gt;mobx-formkit-events&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Event hooks and handlers — &lt;code&gt;onInit&lt;/code&gt;, &lt;code&gt;onChange&lt;/code&gt;, &lt;code&gt;onFocus&lt;/code&gt;, &lt;code&gt;onBlur&lt;/code&gt;, &lt;code&gt;onSubmit&lt;/code&gt;, &lt;code&gt;onSuccess&lt;/code&gt;, &lt;code&gt;onError&lt;/code&gt;, key events.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-observers-interceptors" rel="noopener noreferrer"&gt;mobx-formkit-observers-interceptors&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;MobX observers and interceptors — observing field changes, intercepting mutations, rejecting/modifying values, disposers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-computed" rel="noopener noreferrer"&gt;mobx-formkit-computed&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Reactive computed props and &lt;code&gt;autorun&lt;/code&gt; — computed field values, autorun-derived totals, row calculations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-composer" rel="noopener noreferrer"&gt;mobx-formkit-composer&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The forms composer — orchestrating multiple &lt;code&gt;Form&lt;/code&gt; instances with batch validate/submit/clear/reset.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-converters" rel="noopener noreferrer"&gt;mobx-formkit-converters&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Input/output converters — transforming values between input and store, per-field and separated mode.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-file-upload" rel="noopener noreferrer"&gt;mobx-formkit-file-upload&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;File upload fields — &lt;code&gt;type: file&lt;/code&gt;, drag-and-drop zones, &lt;code&gt;onDrop&lt;/code&gt; hooks, &lt;code&gt;FileList&lt;/code&gt; access, validation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-sortable" rel="noopener noreferrer"&gt;mobx-formkit-sortable&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sortable arrays — &lt;code&gt;move()&lt;/code&gt;, &lt;code&gt;ArrayMap&lt;/code&gt; reordering, drag-and-drop with &lt;code&gt;@dnd-kit&lt;/code&gt;, up/down buttons.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-extend" rel="noopener noreferrer"&gt;mobx-formkit-extend&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Extending &lt;code&gt;Form&lt;/code&gt; and &lt;code&gt;Field&lt;/code&gt; classes — custom field classes, &lt;code&gt;makeField()&lt;/code&gt;, generic and specific extension.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/foxhound87/skills/tree/main/mobx-formkit-options" rel="noopener noreferrer"&gt;mobx-formkit-options&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Form and field options — validation timing, error display, strict modes, debounce, data retrieval.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What the Skills Actually Contain
&lt;/h2&gt;

&lt;p&gt;A skill isn't a vague prompt — it's structured, actionable reference material. The &lt;code&gt;mobx-formkit-validation&lt;/code&gt; skill, for example, documents all six validation drivers with ready-to-use setup snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ZOD — TypeScript-first schema validation&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;zodValidator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobx-formkit/lib/validators/ZOD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;zod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zodValidator&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But more importantly, it encodes the &lt;em&gt;non-obvious&lt;/em&gt; knowledge — the things that trip up both humans and AI models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async validation&lt;/strong&gt;: returning Promises from VJF validators, &lt;code&gt;registerAsync&lt;/code&gt; for DVR, async &lt;code&gt;onChange&lt;/code&gt; hooks that call &lt;code&gt;field.invalidate()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-field validation&lt;/strong&gt; via the &lt;code&gt;related&lt;/code&gt; property, so changing &lt;code&gt;password&lt;/code&gt; re-validates &lt;code&gt;passwordConfirm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The full validation-options matrix&lt;/strong&gt;: &lt;code&gt;validateOnInit&lt;/code&gt;, &lt;code&gt;validateOnBlur&lt;/code&gt;, &lt;code&gt;showErrorsOnChange&lt;/code&gt;, &lt;code&gt;validationDebounceWait&lt;/code&gt;, &lt;code&gt;stopValidationOnError&lt;/code&gt;, and how per-field options override form-level ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugin ordering&lt;/strong&gt; with &lt;code&gt;validationPluginsOrder&lt;/code&gt; when mixing drivers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programmatic invalidation&lt;/strong&gt; with &lt;code&gt;field.invalidate(msg, deep, async)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last category is the real value of agentic skills: the difference between code that &lt;em&gt;works&lt;/em&gt; and code that's &lt;em&gt;idiomatic&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters for AI-Generated Code
&lt;/h2&gt;

&lt;p&gt;Anyone who has used an AI assistant to scaffold a form knows the failure modes: a model that trained on generic form libraries will happily generate &lt;code&gt;useState&lt;/code&gt;-based controlled inputs, invent non-existent methods, or skip the &lt;code&gt;onError&lt;/code&gt; hook entirely. The generated code compiles, renders, and &lt;em&gt;almost&lt;/em&gt; works — until you hit validation.&lt;/p&gt;

&lt;p&gt;Skills eliminate the guesswork. The &lt;code&gt;mobx-formkit-api&lt;/code&gt; skill alone encodes the entire architecture — &lt;code&gt;Form&lt;/code&gt; → &lt;code&gt;fields: ArrayMap&amp;lt;Field&amp;gt;&lt;/code&gt; → state/bindings/validator — plus the full method table, so a model asked to "add a reset button" reaches straight for &lt;code&gt;form.reset()&lt;/code&gt; instead of re-implementing state management.&lt;/p&gt;

&lt;p&gt;There's also a practical benefit beyond correctness: &lt;strong&gt;faster iteration&lt;/strong&gt;. Instead of prompting an agent with context and then debugging the result, the skill gives it the right primitives up front. Fewer rounds of "no, that's not how the API works."&lt;/p&gt;




&lt;h2&gt;
  
  
  The Library's Design Makes This Easy
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mobx-formkit&lt;/code&gt; is unusually well-suited for agentic skills because of its consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Everything is reactive&lt;/strong&gt; — form and field properties are MobX observables, and &lt;code&gt;observer()&lt;/code&gt;-wrapped components re-render automatically. Agents just need to know which properties are computed (&lt;code&gt;isValid&lt;/code&gt;, &lt;code&gt;isDirty&lt;/code&gt;, &lt;code&gt;isPristine&lt;/code&gt;, &lt;code&gt;hasError&lt;/code&gt;...) versus editable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One selector for everything&lt;/strong&gt; — &lt;code&gt;form.$('path')&lt;/code&gt; / &lt;code&gt;form.select()&lt;/code&gt; works for flat, nested, and array fields with the same dot-notation syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative validation&lt;/strong&gt; — rules live in field definitions, so agents can express complex logic as configuration instead of imperative code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uniform extension points&lt;/strong&gt; — &lt;code&gt;plugins()&lt;/code&gt;, &lt;code&gt;hooks()&lt;/code&gt;, &lt;code&gt;bindings()&lt;/code&gt;, and class extension via &lt;code&gt;makeField()&lt;/code&gt; cover almost every customization need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When an API is this regular, a skill can document a small number of patterns that cover a very large space of use cases. That's precisely what makes the skill set effective.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install the skills&lt;/strong&gt; for your agent of choice (opencode, Claude Code, Cursor, and others are supported by skills.sh).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with the core trio&lt;/strong&gt;: &lt;code&gt;mobx-formkit-api&lt;/code&gt;, &lt;code&gt;mobx-formkit-nested&lt;/code&gt;, and &lt;code&gt;mobx-formkit-validation&lt;/code&gt; — they cover the 80% use case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bring in the rest as needed&lt;/strong&gt;: reach for &lt;code&gt;multi-step&lt;/code&gt;, &lt;code&gt;sortable&lt;/code&gt;, or &lt;code&gt;file-upload&lt;/code&gt; when the requirement appears.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let the agent load the skill&lt;/strong&gt; when prompting — e.g., "using the mobx-formkit-validation skill, add cross-field validation for the password fields."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The repository is MIT-licensed and actively maintained by foxhound87 (the author of &lt;code&gt;mobx-formkit&lt;/code&gt; — formerly &lt;code&gt;mobx-react-form&lt;/code&gt; — himself), so the skills track the library's actual behavior — not a stale approximation of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Agent skills represent a shift in how we document libraries: from documentation &lt;em&gt;you&lt;/em&gt; read, to documentation &lt;em&gt;the AI&lt;/em&gt; reads — so the AI can write code as if it had read the docs itself. With 15 skills spanning the full API surface of &lt;code&gt;mobx-formkit&lt;/code&gt; (formerly &lt;code&gt;mobx-react-form&lt;/code&gt;), the &lt;code&gt;foxhound87/skills&lt;/code&gt; repository turns AI assistants into competent React form developers out of the box.&lt;/p&gt;

&lt;p&gt;The era of AI generating &lt;code&gt;useState&lt;/code&gt;-spaghetti for forms is over — at least for anyone willing to spend 30 seconds installing a skill.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Repository: &lt;a href="https://github.com/foxhound87/skills" rel="noopener noreferrer"&gt;github.com/foxhound87/skills&lt;/a&gt; · MIT License · Install via &lt;code&gt;npx skills add https://github.com/foxhound87/skills --all&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;📚 &lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://foxhound87.github.io/mobx-formkit" rel="noopener noreferrer"&gt;mobx-formkit docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://foxhound87.github.io/mobx-formkit-demo" rel="noopener noreferrer"&gt;mobx-formkit-demo&lt;/a&gt; · &lt;a href="https://github.com/foxhound87/mobx-formkit-demo" rel="noopener noreferrer"&gt;demo code&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Why mobx-react-form Is the Best Form Library You're Not Using</title>
      <dc:creator>Cla</dc:creator>
      <pubDate>Sat, 06 Jun 2026 20:00:00 +0000</pubDate>
      <link>https://dev.to/foxhound87/why-mobx-react-form-is-the-best-form-library-youre-not-using-16kd</link>
      <guid>https://dev.to/foxhound87/why-mobx-react-form-is-the-best-form-library-youre-not-using-16kd</guid>
      <description>&lt;p&gt;If you build forms in React, you've probably tried Formik, React Hook Form, or final-form. They're good. But if you deal with &lt;strong&gt;complex, deeply nested, multi-step forms&lt;/strong&gt; — the kind that make you question your life choices — there's a better tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mobx-react-form&lt;/strong&gt; combines MobX reactivity with a powerful form state engine. Here's why it deserves your attention.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Nested Fields Without the Pain
&lt;/h2&gt;

&lt;p&gt;Real forms aren't flat. Take an invoice: you have a customer section, a shipping address, and a variable number of products, each with name, quantity, and price.&lt;/p&gt;

&lt;p&gt;MRF handles this natively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer.name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer.email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shipping.address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shipping.city&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shipping.zip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products[].name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products[].quantity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products[].unitPrice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each path becomes an observable field with its own validation, errors, and dirty tracking. No flattening. No normalization. The values serialize back to exactly the structure your API expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"shipping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"zip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"products"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Widget A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unitPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;19.99&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with &lt;strong&gt;v6.15&lt;/strong&gt;, errors bubble up automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MobxReactForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bubbleUpErrorMessages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// When products[0].product is empty, this just works:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorBanner&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Validation Plugins — Bring Your Own
&lt;/h2&gt;

&lt;p&gt;MRF doesn't lock you into one validator. It supports &lt;strong&gt;6 validation plugins&lt;/strong&gt; out of the box:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Style&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DVR&lt;/td&gt;
&lt;td&gt;validatorjs&lt;/td&gt;
&lt;td&gt;Declarative rules (`'required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VJF&lt;/td&gt;
&lt;td&gt;Custom functions&lt;/td&gt;
&lt;td&gt;{% raw %}&lt;code&gt;(value) =&amp;gt; [isValid, message]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZOD&lt;/td&gt;
&lt;td&gt;zod&lt;/td&gt;
&lt;td&gt;Schema-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YUP&lt;/td&gt;
&lt;td&gt;yup&lt;/td&gt;
&lt;td&gt;Schema-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JOI&lt;/td&gt;
&lt;td&gt;joi&lt;/td&gt;
&lt;td&gt;Schema-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVK&lt;/td&gt;
&lt;td&gt;ajv&lt;/td&gt;
&lt;td&gt;Schema-based&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use DVR for simple fields and ZOD for complex cross-field validation — in the same form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;dvr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dvr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;validatorjs&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;zod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zod&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;invoiceSchema&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define a Zod schema for your entire form and get both client-side validation and TypeScript types from one source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;invoiceSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;positive&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Full TypeScript Generics (v6.13)
&lt;/h2&gt;

&lt;p&gt;If you're on TypeScript, MRF now offers &lt;strong&gt;end-to-end type safety&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;InvoiceForm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;shipping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MobxReactForm&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InvoiceForm&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products[0]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Field&amp;lt;string&amp;gt; — fully typed&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                        &lt;span class="c1"&gt;// InvoiceForm — fully typed&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Acme Corp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// type-safe setter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus &lt;strong&gt;&lt;code&gt;PathsOf&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/strong&gt; for autocomplete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ship&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// → editor suggests: 'shipping.address' | 'shipping.city' | 'shipping.zip'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more guessing field paths. No more runtime errors from typos.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Dynamic &amp;amp; Array Fields
&lt;/h2&gt;

&lt;p&gt;Need to add products dynamically? Remove a shipping address from a list? Built in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add a product&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Remove the second product&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Reorder (new in v6.14 with ArrayMap)&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrays, nested arrays, dynamic field creation — MRF handles all of it with MobX reactivity. Each item gets its own validation lifecycle, dirty tracking, and error state.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Composer — Multi-Form Orchestration
&lt;/h2&gt;

&lt;p&gt;Have independent forms that need to submit together? The &lt;code&gt;composer()&lt;/code&gt; function coordinates validation across forms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;composer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;billing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shipping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payment&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;submitOrder&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;billing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;shipping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shipping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// errors is keyed by form name: { billing: {...}, shipping: {...}, payment: {...} }&lt;/span&gt;
    &lt;span class="nf"&gt;showValidationSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for checkout flows, multi-tab dashboards, and wizard-style UIs where each step is an independent form.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. UI Library Agnostic
&lt;/h2&gt;

&lt;p&gt;MRF works with every major UI library — and doesn't force you to pick one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Material UI&lt;/li&gt;
&lt;li&gt;Ant Design&lt;/li&gt;
&lt;li&gt;React Aria&lt;/li&gt;
&lt;li&gt;Headless UI&lt;/li&gt;
&lt;li&gt;React Widgets&lt;/li&gt;
&lt;li&gt;React-Select&lt;/li&gt;
&lt;li&gt;Plain HTML&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each gets a thin binding layer. The form logic stays the same whether you render with MUI TextFields or raw &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Works the same regardless of UI library&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer.name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer.email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swap the Input component from MaterialTextField to AntdInput to SimpleInput — the form state doesn't care.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Built for Production, Maintained for Years
&lt;/h2&gt;

&lt;p&gt;MRF has been powering production forms for &lt;strong&gt;8+ years&lt;/strong&gt;. It has &lt;strong&gt;1.1k+ GitHub stars&lt;/strong&gt;, and the latest releases (June 2026) brought the most requested features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;v6.15&lt;/strong&gt; — Error bubbling in nested forms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v6.14&lt;/strong&gt; — ArrayMap with predictable ordering and drag-and-drop support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v6.13&lt;/strong&gt; — Full TypeScript generics, strict null checks, path autocomplete&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v6.12&lt;/strong&gt; — Custom validation type inference, YUP &lt;code&gt;.ref()&lt;/code&gt; support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v6.11&lt;/strong&gt; — Full null values support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each release was driven by real production needs, not hypothetical use cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;MRF&lt;/th&gt;
&lt;th&gt;Alternatives&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple login form&lt;/td&gt;
&lt;td&gt;✅ Overkill but works&lt;/td&gt;
&lt;td&gt;✅ Great fit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deeply nested fields (invoice, order, profile)&lt;/td&gt;
&lt;td&gt;✅ Native support&lt;/td&gt;
&lt;td&gt;❌ Requires flattening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic arrays (add/remove/reorder)&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ Manual state mgmt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-form validation (checkout, wizard)&lt;/td&gt;
&lt;td&gt;✅ Composer&lt;/td&gt;
&lt;td&gt;❌ Custom orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation plugins (DVR/ZOD/YUP/JOI)&lt;/td&gt;
&lt;td&gt;✅ 7 plugins&lt;/td&gt;
&lt;td&gt;❌ Usually 1-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript generics + path autocomplete&lt;/td&gt;
&lt;td&gt;✅ v6.13+&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error bubbling in nested forms&lt;/td&gt;
&lt;td&gt;✅ v6.15+&lt;/td&gt;
&lt;td&gt;❌ Manual recursion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI library flexibility&lt;/td&gt;
&lt;td&gt;✅ Any library&lt;/td&gt;
&lt;td&gt;✅ Any library&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you build forms beyond a login page — invoices, checkouts, multi-step registrations, admin panels with dynamic sections — give MRF a try. It handles the complexity so you don't have to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; mobx-react-form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;a href="https://foxhound87.github.io/mobx-formkit-demo" rel="noopener noreferrer"&gt;Try the live demo&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://github.com/foxhound87/mobx-formkit" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://foxhound87.github.io/mobx-formkit" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>mobx</category>
      <category>react</category>
      <category>form</category>
      <category>development</category>
    </item>
  </channel>
</rss>
