Real Frameworks Don't Use Reactive State: They Implement Reactive Attributes and Parameters
The web development community has been obsessed with "reactive state" for over a decade. From Redux to Vuex, from MobX to Zustand, we've built increasingly complex systems to manage application state reactively. But what if we've been solving the wrong problem entirely?
What if real frameworks shouldn't focus on reactive state at all, but instead implement reactive attributes and parameters?
The State Obsession Problem
Modern frameworks have conditioned us to think in terms of centralized, reactive state:
// The React way
const [count, setCount] = useState(0);
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(false);
// The Vue way
const state = reactive({
count: 0,
user: null,
loading: false
});
This approach creates several fundamental problems:
- State becomes the single source of truth - Everything flows through state, creating tight coupling
- Reactive overhead everywhere - Even static values get wrapped in reactive systems
- Mental model complexity - Developers must think about state flow, reducers, actions, and effects
- Performance bottlenecks - Large state trees trigger unnecessary re-computations
The Attribute-First Alternative
Consider a different approach entirely. Instead of reactive state, what if we had reactive attributes and parameters that respond to external changes without requiring centralized state management?
// Juris-style reactive attributes
const UserDisplay = (props, {getState}) => ({
div: {
children: [
{
h1: {
// Reactive attribute - updates when username changes
text: () => `Welcome: ${getState('user.name', 'Guest')}`
}
},
{
h1: {
// Static attribute - evaluates once, never changes
text: `App Version: ${getState('app.version', '1.0.0')}`
}
}
]
}
});
In this model:
- Attributes are individually reactive - Only the properties that need to change are reactive
- No state tree - Data comes from external sources (APIs, localStorage, URL params)
- Surgical reactivity - Only specific DOM properties update when their dependencies change
Why This Matters: Real-World Example
Let's compare building a user profile component:
State-Centric Approach (React/Vue):
// Complex state management
const [user, setUser] = useState(null);
const [avatar, setAvatar] = useState('');
const [status, setStatus] = useState('loading');
useEffect(() => {
fetchUser().then(userData => {
setUser(userData);
setAvatar(userData.avatar);
setStatus('loaded');
});
}, []);
// Component tied to state
return (
<div className="user-profile">
<img src={avatar} alt={user?.name} />
<h2>{user?.name}</h2>
<span className={`status ${status}`}>{status}</span>
</div>
);
Attribute-Centric Approach:
const UserProfile = (props, {getState}) => ({
div: {
className: 'user-profile',
children: [
{
img: {
// Each attribute reactively computes its own value
src: () => getState('user.avatar', '/default-avatar.png'),
alt: () => getState('user.name', 'User')
}
},
{
h2: {
text: () => getState('user.name', 'Loading...')
}
},
{
span: {
className: () => `status ${getState('user.status', 'loading')}`,
text: () => getState('user.status', 'loading')
}
}
]
}
});
Notice the difference:
- No useState, no useEffect, no complex state lifecycle
- Each attribute computes its value independently
- Default values are handled at the attribute level
- The component is a pure description of what the DOM should look like
The Performance Revolution
This attribute-first approach enables profound performance optimizations:
Surgical DOM Updates
// The perfect example of selective reactivity
{
h1: {
text: () => `Current User: ${getState('user.name', 'Guest')}` // Reactive
}
},
{
h1: {
text: `App Name: ${getState('app.title', 'MyApp')}` // Static
}
}
// When user.name changes, only the first h1's text content updates
// The second h1 never changes, even though it uses the same getState API
Traditional reactive frameworks must:
- Detect state change
- Mark component as dirty
- Re-run entire component function
- Diff virtual DOM
- Apply changes to real DOM
Attribute-reactive frameworks can:
- Detect data change
- Update specific DOM attribute directly
Memory Efficiency
State-centric frameworks keep entire component trees in memory:
// React's approach - entire virtual DOM tree stored
const virtualDOM = {
type: 'div',
props: { className: 'user-profile' },
children: [
{ type: 'img', props: { src: avatar, alt: name } },
{ type: 'h2', props: {}, children: [name] }
// ... entire tree structure
]
};
Attribute-reactive frameworks only store the reactive functions:
// Only the reactive computations are stored
const reactiveBindings = [
{ element: imgEl, attribute: 'src', compute: () => getState('user.avatar') },
{ element: h2El, attribute: 'textContent', compute: () => getState('user.name') }
];
Breaking Free from the State Mental Model
The shift from reactive state to reactive attributes represents a fundamental change in how we think about web applications:
Old Mental Model: State → UI
- Define state shape
- Create state management (reducers, actions, etc.)
- Connect components to state
- Handle state updates and side effects
New Mental Model: Data → Attributes
- Define what attributes need to be dynamic
- Specify where each attribute gets its data
- Let the framework handle the reactivity
Real Framework Characteristics
A "real" framework in this context has these characteristics:
1. Attribute Granularity
Individual DOM attributes are reactive units, not entire components or state trees.
2. External Data Sources
Data comes from APIs, databases, localStorage, URL parameters - not internal state management.
3. Declarative Binding
You declare what each attribute should be, not how to update it.
4. Zero State Ceremony
No useState, no reducers, no actions - just direct data-to-attribute mappings.
The Juris Example
Juris demonstrates this philosophy in practice:
const Dashboard = (props, {getState}) => ({
main: {
className: 'dashboard',
children: [
{
header: {
// Reactive attribute: updates when user data changes
textContent: () => `Dashboard - ${getState('user.name', 'Guest')}`,
// Static attribute: never changes
role: 'banner'
}
},
{
div: {
// Reactive style based on theme
style: () => ({
backgroundColor: getState('theme.background', '#ffffff')
}),
children: [
{
p: {
// Static content - company name never changes
text: `© ${getState('company.name', 'Acme Corp')} 2025`
}
},
{
p: {
// Reactive content - updates with live data
text: () => `Active Users: ${getState('stats.activeUsers', 0)}`
}
}
]
}
}
]
}
});
Each attribute computes its value independently. There's no central state to manage, no complex update cycles, no component lifecycle to reason about.
The Implications
This shift has profound implications for how we build web applications:
For Performance
- Surgical updates eliminate unnecessary work
- Memory usage scales with reactive attributes, not component count
- No virtual DOM overhead
For Developer Experience
- Less mental overhead - no state management complexity
- More predictable - each attribute's behavior is isolated
- Easier debugging - attribute computations are pure functions
For AI Collaboration
- Simpler patterns for AI to understand and generate
- No complex state flow to track
- Direct mapping from requirements to implementation
The Resistance
Why hasn't this approach taken over? Several factors:
Ecosystem Lock-in
Millions of developers are trained in state-centric patterns. The job market, tutorials, and tooling all assume reactive state.
Component Reusability Myths
The belief that components should be self-contained with their own state creates artificial boundaries that prevent optimal attribute-level reactivity.
Framework Vendor Interest
Complex state management creates vendor lock-in. Simple attribute reactivity is harder to monetize and differentiate.
Conclusion: The Future is Attribute-Native
The next generation of web frameworks will likely embrace attribute-first reactivity. As we move toward AI-assisted development and performance-critical applications, the simplicity and efficiency of reactive attributes becomes undeniable.
The question isn't whether this shift will happen, but how quickly the development community will recognize that reactive state was always the wrong abstraction.
Real frameworks don't manage state - they connect data to attributes and get out of the way.
The revolution isn't coming. It's already here, in frameworks like Juris that dare to question our fundamental assumptions about how web applications should work.
Website: https://jurisjs.com/
GitHub: https://github.com/jurisjs/juris
NPM: https://www.npmjs.com/package/juris
Codepen: https://codepen.io/jurisauthor
Online Testing: https://jurisjs.com/tests/juris_pure_test_interface.html
Top comments (1)
Thank you :-)