Managed state for ReactMore application,for less code.
Expressive MVC moves data, behavior, and lifecycle into focused models. Components stay small, application logic stays readable, and every feature takes less code to build, test, and change.
Drops into React you already have - not a framework, no rewrite.
React has gotten complicated.
Hooks accumulate with features. Their logic stays tied to React. Wiring them makes components larger, tightly coupled, and difficult to trace.
React renders your app.
MVC keeps it organized.
Expressive MVC is a model layer for your app. It gives data, async and side effects a home away from display logic. Components stay simple and behavior easy to read, write and debug.
Smaller components
Focus on the display logic, not coordinating features.
Separated concerns
Break up features so growth isn't tech debt.
Less Ceremony
Normal logic, without the factories and wrappers.
Higher Clarity
Review agent output with confidence, not gymnastics.
The same logic. Half the noise.
Say you want a reusable, component-owned useFooBarBaz that re-renders on change. Examples have same state and behavior. Expressive gets there with less code.
import React from 'react';import State from '@expressive/react';class FooBarBaz extends State { foo = 0; bar = 'hello'; baz = true; bump() { this.foo++; }}function Widget() { const { foo, bar, baz, bump } = FooBarBaz.use(); return ( <button onClick={bump}> {foo} · {bar} · {String(baz)} </button> );}With MVC, destructuring is your dependency list. Just read a field to subscribe to it. No setters, dependency arrays, or memoized callbacks.
Classes are their own context.
Wrap a subtree in <Provider for={X}> - components inside need only X.get() to interact with the nearest instance. Fully typed, zero boilerplate.
No createContext<T>, null default, missing-provider guard to write and maintain. Every app needs this eventually. Jotai's Provider will wrap a whole atom store, MobX leaves it to you.
Component is renderable State.
Component is for self-contained (or extensible) display logic. Fields drive getters and render() directly - destructure this as you would use hook.
A Component provides itself too, accessible to children without prop drilling.
Rails for your React app.
MVC covers stateful behavior you normally need a library for. Build forms, tables, and modals on the same foundation. The only opinions are your own.
Better architecture, better output.
Clear conventions mean a good feature looks the same, whether written by you, your team, or an agent. AI-generated code stays readable and high quality.
Dense business logic
State, derived values, async, and lifecycle live together. Composition helps separate concerns into readable chunks.
Type-safe as a rule
Classes pair naturally with TypeScript and JSDoc, so editors surface types and intent where the work is.
Less to trace when things break
No dependency arrays, stale closures, or complicated interactions. A fix starts at the class, not a hunt through wiring.
Class instances are just objects
The instance is the source of truth. Log it, assert on it, or bind it to window to inspect directly.
A layer, not a leap.
Start with the feature already hurting and leave the rest alone. MVC works with the React app and tools you already have.
Incremental adoption
No big-bang rewrite. Adopt it one feature at a time and leave simple useState calls alone. A tool for complexity, not a replacement.
Keep what works
MVC doesn't need to replace every hook or specialist library. Keep the tools that still earn their place.
Portable state
Headless State classes don't depend on a component tree. Move them, test them, or use the framework-agnostic core.
No build-time magic
MVC adds no compiler, code generation, or custom syntax. What you write is what runs.
Move just one feature out of hooks.
Start with one, leave the rest. See how it feels.
The agent skill gives your coding agent the full API and best practices.