helux

repository·master·Indexed 23 days ago

https://github.com/heluxjs/helux

A high-performance reactive atomic state engine for React (including React 18) and React-like frameworks. It integrates atoms, signals, dependency tracking, derivation, and observation to support fine-grained updates. The library provides tools for shared state management via createShared and useShared, a Service Pattern implementation via useService, and utility packages such as @helux/f-guard for concurrency protection and @helux/f-noop for empty function implementations.

Tokens
75.4K
Snippets
192
Records
345
Agent score
79%

What's inside helux

  1. Overview of Helux Base API functions

    master

    The Helux base API provides a set of fundamental functions for state management, reactivity, and data flow. These functions can be categorized into several core capabilities:

    State Creation

    • Atoms: Use atom (returns a tuple) or atomx (returns a dictionary) to create basic state objects.
    • Shared State: Use share (returns a tuple) or sharex (returns a dictionary) to create dictionary-type atom objects.
    • Granular Reactivity: Use signal for DOM-level updates or block/dynamicBlock for block-level updates.

    Derivation and Mutation

    • Derivation (Read-only): Define derived state using derive (single) or deriveDict (batch). For asynchronous tasks, use defineDeriveTask or defineDeriveFnItem to benefit from automatic dependency type inference. Trigger derivations manually with runDerive or runDeriveTask.
    • Mutation (Writeable): Define mutable derived functions using mutate (single) or mutateDict (batch). Trigger them manually with runMutate or runMutateTask.

    Actions and Side Effects

    • Actions: Create synchronous or asynchronous functions to modify state using action.
    • Observation: Monitor data changes using watch or watchEffect (which runs immediately and collects dependencies on the first run).
    • Events: Use emit to dispatch events and on to listen for them.

    Data Synchronization

    • Two-way Binding: Use syncer for shallow object synchronization or sync for deep object synchronization to assist with two-way data binding.
  2. Overview of Helux Hooks

    master
    Helux provides a suite of hooks for interacting with different types of state and reactive primitives within a component. These hooks allow you to consume atoms, reactive objects, derived state, and services, while also providing utilities for side effects (watching), event handling, and managing loading states for mutations and actions.
  3. Overview of Helux features and capabilities

    master

    Helux is a high-performance state engine that integrates atom, signal, and dependency tracking. It is designed for fine-grained reactive updates and is compatible with all React-like libraries, including React 18.

    Key features include:

    • High Performance: Built on limu (an immutable JS library) with built-in dependency tracking.
    • DDD Friendly: atom supports arbitrary data structures with built-in dependency collection, making it suitable for Domain-Driven Design without needing to split state into tiny pieces.
    • Fine-grained Updates: Built-in signal mechanism allows for DOM or block-level updates with zero hooks.
    • Async Management: A built-in loading module manages asynchronous task states and error propagation to components and plugins.
    • Two-way Binding: A sync API series supports two-way binding, simplifying form handling.
    • Reactive Objects: Built-in reactive objects allow data changes to directly drive UI rendering.
    • Modular Architecture: define APIs facilitate modular state abstraction for large-scale frontend applications.
    • Flexible Derivation:
      • Mutable Derivation: For scenarios where changes to specific nodes in a shared object should trigger updates in other nodes with minimal granularity.
      • Full Derivation: For scenarios where fine-grained updates are not required.
      • Both support asynchronous tasks and manual re-triggering.
    • Extensibility: Includes an event system and a middleware/plugin system that integrates with the Redux ecosystem.
    • Type Safety: 100% TypeScript codebase.
  4. Use @helux/f-noop for empty functions

    master

    @helux/f-noop is a collection of no-op (empty) functions and factory functions used to provide safe, empty implementations for various types and async requirements. This is useful for satisfying type requirements or providing default callbacks that do nothing.

    import { noopAny } from '@helux/f-noop';
    
    const fn = noopAny;
    fn();
  5. Core API Reference Overview

    master

    Helux provides a comprehensive set of APIs for state management, categorized into Base APIs, Shared Context, Hooks, and Utilities.

    Base APIs

    Used for creating state containers and defining reactive logic:

    • Atoms: atom (returns tuple), atomx (returns dictionary), share (dictionary-type atom, returns tuple), sharex (dictionary-type atom, returns dictionary).
    • Granular Updates: signal (DOM-level updates), block (block-level updates), dynamicBlock (dynamic block updates during component rendering).
    • Derivations: derive (single full derivation), deriveDict (batch full derivations), defineDeriveTask (async task helper), defineDeriveFnItem (async task helper), runDerive (manual trigger), runDeriveTask (manual async trigger).
    • Mutations: mutate (single mutable derivation), mutateDict (batch mutable derivations), runMutate (manual trigger), runMutateTask (manual async trigger).
    • Actions & Side Effects: action (sync/async state modifiers), watch (data change listeners), watchEffect (immediate listeners with dependency collection), syncer/sync (two-way binding helpers), emit (event emission), on (event listening).
  6. What is a Full Derivation (全量派生)?

    master

    A Full Derivation (全量派生) is a function that listens to changes in specific data nodes within the shared state and returns an entirely new piece of data.

    When a full derivation function is executed for the first time, it automatically collects and records all external data dependencies it accesses. This allows the function to re-run whenever any of those dependencies change.

    import { derive, atom } from 'helux';
    
    const [numAtom] = atom(1); // { val: 1 }
    const plus100Result = derive(() => numAtom.val + 100); // { val: 101 }
  7. What is a Mutable Derivation (可变派生)?

    master

    A Mutable Derivation (可变派生) is a function that listens to changes in its own data nodes or external shared state nodes, and in response, triggers a modification of other data nodes within its own state.

    Like full derivations, mutable derivations collect and record all external data dependencies during their first execution.

  8. How dependency collection works

    master

    Helux supports real-time dependency collection during component rendering. When you use useAtom to access specific properties of an object stored in an atom, helux tracks which properties were accessed. This ensures that a component only re-renders when the specific properties it depends on change, rather than re-rendering on any change to the atom.

    import { useAtom } from 'helux';
    const [objAtom, setObj] = atom({ a: 1, b: { b1: 1 } });
    
    // Modify the draft and generate a new state with shared data structure. 
    // The current modification will only trigger the rendering of the Demo1 component.
    setObj((draft) => (draft.a = Math.random()));
    
    function Demo1() {
      const [obj] = useAtom(objAtom);
      // Trigger re-rendering only when obj.a changes
      return <h1>{obj.a}</h1>;
    }
    
    function Demo2() {
      const [obj] = useAtom(objAtom);
      // Trigger re-rendering only when obj.b.b1 changes
      return <h1>{obj.b.b1}</h1>;
    }
  9. Use Signal for fine-grained UI updates

    master

    Helux provides a signal mechanism to bind raw state values directly to the view. This allows for DOM-level or block-level updates without triggering a full component re-render.

    • Raw value response: Use the $(atom) syntax to bind a value.
    • Block response: Use the block function to wrap a chunk of UI that should only update when its specific dependencies change.
    // 1. Raw value response (only updates the h1 text node)
    <h1>{$(numAtom)}</h1>
    
    // 2. Formatted signal
    <h1>{$(numAtom, num => `hi helux ${num.val}`)}</h1>
    
    // 3. Block response (updates the entire div block only when dependencies change)
    import { block } from 'helux';
    const UserBlock = block(() => (
      <div>
        <h1>{objAtom.a}</h1>
        <h1>{objAtom.b.b1}</h1>
      </div>
    ));
    
    <UserBlock />
  10. Modify primitive atoms using reactiveRoot

    master

    When working with primitive (atomic) types, the reactive value returned by useReactive is the unboxed primitive value itself. Because primitives are passed by value in JavaScript, you cannot mutate them directly to trigger updates.

    To modify a primitive atom, you must use the second element of the useReactive tuple, reactiveRoot, and update its .val property.

    import { atom, useReactive } from 'helux';
    
    const [numAtom] = atom(1);
    
    function Demo() {
      const [state, stateRoot] = useReactive(numAtom);
      
      const change = () => {
        // state is just the number, stateRoot.val is the mutable reference
        stateRoot.val += 1;
      };
      
      return <h1 onClick={change}>{state}</h1>;
    }
  11. Understand Draft and State types

    master

    Helux uses specific types to distinguish between mutable 'draft' objects used during mutations and read-only 'state' objects used for consumption.

    • DraftRootType: The type of the root object returned by share. If the state is an Atom, the root is the Atom itself. Otherwise, it is the state type T.
    • DraftType: The type of the actual mutable data. If the state is an Atom, this is the value inside the atom (AtomDraftVal<T>).
    • StateRootType / StateType: These represent the read-only versions of the state, typically used for observing data without being able to mutate it directly.