---
tagName: 10.0.0-beta.5
name: Effect-Based Reactivity System
publishedAt: '2025-07-09T18:37:36Z'
isPrerelease: false
isDraft: false
---
# Effect-Based Reactivity System

## Neo.mjs v10.0.0-beta.5 Release Notes

This beta release dramatically expands on the reactive programming model introduced in beta.4, delivering a powerful, end-to-end **Effect-Based Reactivity System**. This new system provides a declarative and highly efficient way to manage component state, create reactive data transformations, and build dynamic user interfaces with minimal boilerplate.

This release also includes significant enhancements to the framework's mixin system and state providers, further improving code organization and state management capabilities.

### Core Framework & Features

A core philosophy of Neo.mjs is to provide developers with powerful, flexible options. This release reinforces that principle by dramatically enhancing the framework's reactive core. These new features provide a more direct, declarative way to manage state and build UIs—offering a familiar entry point for developers from other ecosystems—while seamlessly integrating with the established power and productivity of Neo.mjs's declarative component tree architecture.

The pace of innovation in this release is a testament to the power and flexibility of the new architecture. The features introduced in this beta represent a quantum leap forward, enabling development patterns that are more declarative, more powerful, and more intuitive than ever before.

#### 1. The New Effect-Based Reactivity System

The core of this release is a new suite of classes (`core.Effect`, `core.EffectManager`, `core.BatchEffectManager`) that enable true "spreadsheet-style" reactivity. An "Effect" is a function that automatically re-runs whenever any of its reactive dependencies change.

*   **Automatic Dependency Tracking**: The framework now automatically tracks which reactive configs are accessed within an Effect. You declare a config as reactive by adding a trailing underscore in the `static config` block (e.g., `myValue_`), and then access it without the underscore (`this.myValue`). You no longer need to manually subscribe to changes; the dependency graph is built and maintained for you.
*   **Arbitrary Cross-Instance Bindings**: Since bindings are now powered by `core.Effect`, they can depend on any reactive config from any `core.Base` instance—not just components or state provider `data`. This allows for creating powerful, arbitrary data flows between any part of your application (e.g., binding a component's property to a data store's `count`).
    ```javascript
    // A component can now bind its text to its provider's data AND a store's count
    bind: {
        text: data => `${data.title}: ${myStore.count} items`
    }
    ```
*   **Synchronous Batching (`core.BatchEffectManager`)**: Multiple state changes can be batched together into a single, atomic update. This prevents "glitching" (where the UI updates multiple times for a single user action) and ensures that effects run only once with the final, consistent state.
*   **Foundation for Declarative VDOM**: The new Effect system lays the groundwork for a truly declarative component model. As a proof-of-concept, a new `button.Effect` class was created to demonstrate that a component's VDOM can now be generated by a single, reactive function that automatically re-runs when its state dependencies change. This powerful new paradigm, which will be fully realized in the upcoming **[Functional Components](https://github.com/neomjs/neo/issues/6992)** epic, will make component rendering logic more readable, centralized, and easily extensible.
*   **Lifecycle-Aware Subscriptions**: A new `core.Base#observeConfig()` method provides a safe, convenient way to subscribe to config changes, automatically handling the cleanup of subscriptions when a component is destroyed to prevent memory leaks.

#### 2. Architectural Evolution: State Management Overhaul

`state.Provider` has been completely rewritten to be more powerful, explicit, and performant, leveraging the new Effect-based reactivity core. This is a significant architectural evolution from the previous version.

**The Old System:** Bindings received a single, implicitly merged `data` object, which was a combination of all state providers in the component's hierarchy.

**The New System:** The new model is more explicit and powerful, providing clearer data flow and eliminating "magic".

*   **Reactive Data Proxies**: The `data` object of a provider is now a deep Proxy. You can now trigger reactive updates simply by direct assignment (`myProvider.data.foo = 'new value'`), and any component bound to that data will update automatically.
*   **Intelligent Hierarchical Data Access**: The `data` object passed to bindings and formulas is now a smart proxy. It provides a unified view of the data from the entire provider hierarchy. When you read a property (`data.someValue`), the proxy intelligently searches up the component tree to find the closest provider that owns it. When you write a property using `myProvider.setData('someValue', ...)`, it intelligently finds the correct provider in the hierarchy that already owns the property and updates it there, preventing accidental name collisions and making state updates safe and predictable.
*   **Formulas**: State providers now support formulas—functions that derive their value from other state properties (e.g., `fullName: data => `${data.firstName} ${data.lastName}``). These formulas are themselves reactive and will automatically re-calculate when their dependencies change.
*   **Two-Way Bindings**: Two-way data bindings kept the same power as before, powered by the original config system.

#### 3. Enhanced Class System

*   **Automatic Static Config Merging for Mixins**: The framework's mixin system is now significantly more powerful. Previously limited to methods, mixins can now contribute to the `static config` of a class. The configs are intelligently merged with a clear order of precedence:
    1.  The target class's own `static config` always has the highest priority.
    2.  For conflicting configs between mixins, the mixin that appears *earlier* in the `mixins` array wins.
    3.  Mixins on a base class take precedence over mixins on an extended class.
*   **Granular Cloning Strategies**: The reactive config system now features `clone` and `cloneOnGet` descriptor flags, providing fine-grained control over how and when config values are cloned. This is critical for performance tuning and handling complex data types.

### New Learning Content

*   **New Guide: "Declarative VDOM with Effects"**: A new guide has been added to the documentation to explain the principles of the new reactivity system and demonstrate how to build components using an Effect-based approach.

### Quality & Stability
*   This release includes a comprehensive suite of new unit tests covering the Effect-based reactivity system, the `state.Provider`, and the enhanced `static config` merging. This ensures the stability and correctness of these foundational new features and helps prevent future regressions.

---

All changes combined in 1 commit: https://github.com/neomjs/neo/commit/2105ea95b8b498c73d9c54f6bffe8de8704dfe0d

This release represents a major leap forward for the Neo.mjs framework, providing a state-of-the-art reactive programming model that is both powerful and easy to use.

### Call To Action

We are incredibly excited for you to explore these new capabilities.

*   **Explore Effects**: Try creating your own effects to manage component logic and state.
*   **Leverage State Providers**: Experiment with the new Proxy-based data objects and formulas in `state.Provider`.
*   **Read the New Guide**: Check out the [Declarative VDOM with Effects guide](https://github.com/neomjs/neo/blob/dev/learn/guides/fundamentals/DeclarativeVDOMWithEffects.md) to get started with the new paradigm.
*   **Share Your Feedback**: Your insights are invaluable. Please share your experiences and report any issues via [GitHub Issues](https://github.com/neomjs/neo/issues) or our [Slack Channel](https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA).
