LearnNewsExamplesServices
Frontmatter
id6992
titleFunctional Components
stateOpen
labels
enhancementepicno auto close
assignees[]
createdAtJul 9, 2025, 12:50 PM
updatedAtOct 14, 2025, 9:37 AM
githubUrlhttps://github.com/neomjs/neo/issues/6992
authortobiu
commentsCount1
parentIssuenull
subIssues
6993 Create `Neo.component.mixin.VdomLifecycle`
6994 Create `Neo.functional.component.Base`
6995 Create Interoperability Layer
6996 Encourage Pure VDOM Effects
6997 Implement Effect Memoization
7010 Proof of Concept: Beginner Mode Functional Component
7011 DOM Event Handling for Beginner Mode Functional Components
7012 Create `Neo.functional.useConfig` Hook
7013 Create `Neo.functional.defineComponent` Factory
7014 Enhance `Neo.functional.component.Base` for Hook Support
7015 Enhance `Neo.core.Effect` Constructor
7016 functional.component.Base: enhance the module export
7017 mixin.component.VdomLifecycle => mixin.VdomLifecycle
7019 Refactor `defineComponent` and Enhance Config System Documentation
7021 mixin.VdomLifecycle: createVdomReference()
7022 examples.functional.defineComponent
7027 Feature: Robust Synchronous Updates for Functional Components
7025 Fix: EffectBatchManager.endBatch() Infinite Loop Prevention
7024 Refactor `Neo.core.Effect` to Use a Reactive `isRunning` State
7023 Enhance `Neo.core.Config` for Robust Subscriptions with Scope
7026 Feature: Fine-grained Reactivity Control with EffectManager.pause()
7028 Feature: Centralized Functional Component Exports via _export.mjs
7042 Regression: Neo.core.Effect.run() executes twice
7043 Refactor: Extract DOM Event Handling to `DomEvents` Mixin
7046 Reactive Updates for Nested Components in Functional VDOM
7047 Task: Create Example for Deeply Nested Components
7050 Task: Enhance functional.component.Base with Core Configs
7053 Architectural Enhancement: Implement VDOM Config Diffing in FunctionalBase
7054 Architectural Enhancement: Recursive VDOM Config Diffing for Nested Components
7055 examples.ConfigurationViewport: make createConfigurationComponents() optionally async
7057 Enable support for nesting functional components
7062 functional.component.Base: enhance the `destroy()` signature
7069 Enhance LivePreview for Modern JavaScript and Functional Components
7070 learn/tutorials/TodoList: create a `functional.component.Base` version
7071 layout.Flexbox: applyChildAttributes() => opt out for functional cmps
7074 Improve Functional Component Initial Render Timing
7075 Enable Granular VDOM Updates for Functional Components
subIssuesCompleted35
subIssuesTotal37
blockedBy[]
blocking[]

Functional Components

Openenhancementepicno auto close
tobiu
tobiu commented on Jul 9, 2025, 12:50 PM

Epic: Functional Components

Motivation

This initiative will establish a new, lightweight base class for components. This class will bypass the traditional items array and layout system. Instead, it will be driven by a central Effect that calls a VDOM-generating method (e.g., createVdom()) to declaratively build the component's UI based on its current state. This aligns with the reactive patterns of other popular frameworks and provides a more intuitive and familiar entry point for those developers.

This epic will be broken down into several sub-tickets to implement this new component architecture in an iterative and isolated manner.

Functional Components are an addition to, and not a replacement for declarative component trees based on container.Base: items.


Two Modes of Functional Component Definition

Neo.mjs will offer two distinct ways to define functional components, catering to different developer preferences and needs. Both modes leverage the underlying Neo.functional.component.Base class and the Neo.core.Effect system for reactive rendering, but they provide different levels of abstraction and access to the framework's full power.

1. Beginner Mode: Pure Function with Hooks (e.g., Neo.functional.defineComponent)

This mode is designed for developers seeking a highly concise and familiar syntax, especially those coming from frameworks like React. Components are defined as plain JavaScript functions that return VDOM. State management is handled via dedicated hooks (e.g., useConfig).

Characteristics:

  • Concise Syntax: Focus on the VDOM rendering logic.
  • Hook-based State: State and side effects are managed through use hooks.
  • Simplified API: Abstracts away class boilerplate.
  • Tier 1 Reactivity: Primarily leverages Neo.core.Config for reactive values and Neo.core.Effect for re-rendering.
  • No Lifecycle Hooks: Does not expose beforeGet, beforeSet, or afterSet lifecycle hooks directly on the component definition, as these are tied to the class-based static config system.

2. Medium Mode: Class-based Functional Component (Extending Neo.functional.component.Base)

This mode provides direct access to the underlying Neo.functional.component.Base class, allowing developers to define components using static config properties. This offers a more explicit and powerful way to define reactive components within the Neo.mjs class system.

Characteristics:

  • Explicit Configs: State is defined via static config properties.
  • Full Two-Tier Reactivity: Access to both Neo.core.Config (Tier 1) and the autoGenerateGetSet mechanism (Tier 2), including afterSet lifecycle hooks for imperative side effects.
  • Class-based Structure: Familiar to developers comfortable with class-based component patterns.

Example usage:

import {defineComponent, useConfig} from '../../../src/functional/_export.mjs';
import Button                       from '../../../src/button/Base.mjs';

export default defineComponent({
    config: {
        className: 'Neo.examples.functional.hostComponent.Component'
    },
    createVdom() {
        const [count, setCount] = useConfig(0);

        return {cn: [
            {
                tag : 'p',
                text: `Button clicked ${count} times`
            }, {
                module : Button,
                id     : 'myButtonModule',
                theme  : 'neo-theme-neo-light',
                text   : 'Click Me (Neo Button)',
                handler: () => setCount(prev => prev + 1)
            }
        ]}
    }
});
tobiu added the enhancement label on Jul 9, 2025, 12:50 PM
tobiu added the epic label on Jul 9, 2025, 12:50 PM
tobiu added sub-issue #6993 on Jul 9, 2025, 12:52 PM
tobiu added sub-issue #6994 on Jul 9, 2025, 12:53 PM
tobiu added sub-issue #6995 on Jul 9, 2025, 12:54 PM
tobiu added sub-issue #6996 on Jul 9, 2025, 12:57 PM
tobiu added sub-issue #6997 on Jul 9, 2025, 12:57 PM
tobiu added sub-issue #7010 on Jul 11, 2025, 3:57 AM
tobiu added sub-issue #7011 on Jul 11, 2025, 3:59 AM
tobiu added sub-issue #7012 on Jul 11, 2025, 4:05 AM
tobiu added sub-issue #7013 on Jul 11, 2025, 4:07 AM
tobiu added sub-issue #7014 on Jul 11, 2025, 12:23 PM
tobiu added sub-issue #7015 on Jul 11, 2025, 12:27 PM
tobiu added sub-issue #7016 on Jul 11, 2025, 12:55 PM
tobiu added sub-issue #7017 on Jul 11, 2025, 1:19 PM
tobiu added sub-issue #7019 on Jul 11, 2025, 6:32 PM
tobiu added sub-issue #7021 on Jul 12, 2025, 2:04 PM
tobiu added sub-issue #7022 on Jul 12, 2025, 2:30 PM
tobiu added sub-issue #7027 on Jul 12, 2025, 8:23 PM
tobiu added sub-issue #7025 on Jul 12, 2025, 8:27 PM
tobiu added sub-issue #7024 on Jul 12, 2025, 8:28 PM
tobiu added sub-issue #7023 on Jul 12, 2025, 8:29 PM
tobiu added sub-issue #7026 on Jul 12, 2025, 8:29 PM
tobiu added sub-issue #7028 on Jul 12, 2025, 8:46 PM
tobiu added sub-issue #7042 on Jul 13, 2025, 1:57 PM
tobiu added sub-issue #7043 on Jul 13, 2025, 7:13 PM
tobiu added sub-issue #7046 on Jul 14, 2025, 3:48 PM
tobiu added sub-issue #7047 on Jul 14, 2025, 4:03 PM
tobiu added sub-issue #7050 on Jul 14, 2025, 4:54 PM
tobiu added sub-issue #7053 on Jul 14, 2025, 6:36 PM
tobiu added sub-issue #7054 on Jul 14, 2025, 7:26 PM
tobiu added sub-issue #7055 on Jul 15, 2025, 10:29 AM
tobiu added sub-issue #7057 on Jul 15, 2025, 3:17 PM
tobiu added sub-issue #7062 on Jul 15, 2025, 7:42 PM
tobiu added sub-issue #7069 on Jul 16, 2025, 1:45 AM
tobiu added sub-issue #7070 on Jul 16, 2025, 3:02 AM
tobiu added sub-issue #7071 on Jul 16, 2025, 4:34 AM
tobiu added sub-issue #7074 on Jul 16, 2025, 1:29 PM
tobiu added sub-issue #7075 on Jul 16, 2025, 2:50 PM
tobiu removed the stale label on Oct 14, 2025, 9:37 AM
tobiu added the no auto close label on Oct 14, 2025, 9:37 AM