DEV Community

Pinoy Codie
Pinoy Codie

Posted on

Real Frameworks Don't Use Reactive State: They Implement Reactive Attributes and Parameters

Codepen Demo of Static vs. Reactive

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
});
Enter fullscreen mode Exit fullscreen mode

This approach creates several fundamental problems:

  1. State becomes the single source of truth - Everything flows through state, creating tight coupling
  2. Reactive overhead everywhere - Even static values get wrapped in reactive systems
  3. Mental model complexity - Developers must think about state flow, reducers, actions, and effects
  4. 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')}`
        }
      }
    ]
  }
});
Enter fullscreen mode Exit fullscreen mode

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>
);
Enter fullscreen mode Exit fullscreen mode

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')
        }
      }
    ]
  }
});
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Traditional reactive frameworks must:

  1. Detect state change
  2. Mark component as dirty
  3. Re-run entire component function
  4. Diff virtual DOM
  5. Apply changes to real DOM

Attribute-reactive frameworks can:

  1. Detect data change
  2. 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
  ]
};
Enter fullscreen mode Exit fullscreen mode

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') }
];
Enter fullscreen mode Exit fullscreen mode

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

  1. Define state shape
  2. Create state management (reducers, actions, etc.)
  3. Connect components to state
  4. Handle state updates and side effects

New Mental Model: Data → Attributes

  1. Define what attributes need to be dynamic
  2. Specify where each attribute gets its data
  3. 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)}`
              }
            }
          ]
        }
      }
    ]
  }
});
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
artydev profile image
artydev

Thank you :-)