Zedux

repository·master·Indexed 19 days ago

https://github.com/omnistac/zedux

A molecular state engine for React (version 2.0.0-rc.19) that combines atomic state management with dependency injection and signals. It functions as both a cache manager and a standard state manager. The ecosystem includes @zedux/atoms for framework-independent atomic models, @zedux/core for composable stores, @zedux/react for React-specific hooks and components, and specialized extensions like @zedux/immer for mutable-style updates and @zedux/machines for state machine logic.

Tokens
151.3K
Snippets
449
Records
560
Agent score
66%

What's inside zedux

  1. What is Zedux?

    master

    Zedux is a multi-paradigm state management engine for React. It combines a powerful signals implementation with a Dependency Injection (DI)-driven atomic architecture.

    It functions as both a cache manager and a state manager, offering features like:

    • Real Dependency Injection
    • Rich events
    • Opt-in mutation proxying
    • An extension model patterned after React
  2. Introduction to Zedux

    master

    Zedux is a multi-paradigm state management engine for React. It uses a composable store model built on a Dependency Injection (DI) driven atomic architecture. It is designed to scale from simple local state to highly complex, volatile global state (such as web socket-driven trading platforms).

    Key characteristics include:

    • Atomic Architecture: Uses atoms for granular state.
    • Composable Stores: Allows for complex state hierarchies.
    • Standardized Primitives: Provides consistent ways to interface with 3rd-party state via Composable stores, Injectors, and Atom templates.
    • Flexibility: Supports zero-configuration for simple use cases while providing low-level APIs for advanced requirements.
    • Scalability: Designed to handle code-splitting, lazy-loading, and micro-frontend architectures efficiently.
  3. Understand the Zedux API structure

    master

    The Zedux API is organized into seven primary categories that define how you interact with the library. Depending on your use case (React integration, core logic, or TypeScript definitions), you will primarily interact with one or more of the following:

    • Factories: The primary entry points used to instantiate Zedux classes.
    • Classes: The core JavaScript objects returned by factories; these represent the underlying logic and state containers.
    • Hooks: React-specific hooks designed for use within React function components.
    • Components: Pre-built React components exported by Zedux.
    • Injectors: Specialized objects used within Atom state factories to manage dependencies.
    • Types: TypeScript definitions and data shapes for type-safe development.
    • Utils: Helper functions and miscellaneous tools to support working with classes and types.
  4. What is an Unrestricted Injector?

    master

    An Unrestricted Injector is a special type of injector that relaxes the standard rules of injector usage.

    While they must still be called synchronously during the evaluation of an atom state factory, unlike normal injectors, they can be used inside control flow statements (if, for, while) or after early returns.

    Common examples include:

    • injectAtomGetters()
    • injectInvalidate()
    • injectWhy()
  5. What is Zedux and its core architecture

    master

    Zedux is a 'Molecular State Engine for React' designed for high-performance, scalable state management in complex applications.

    Its architecture is built on two primary layers that are decoupled to enable powerful Dependency Injection (DI) and inter-store communication:

    1. Stores (State Management Layer): Responsible for holding and managing the actual state.
    2. Atoms (Architecture Layer): Provides an atomic model that sits on top of the stores. This layer allows for fine-grained reactivity and efficient selector performance.

    This separation is specifically designed to handle highly volatile state (e.g., socket-driven applications) and to improve Developer Experience (DevX) and runtime performance compared to traditional Flux-based models.

  6. What is an Action in Zedux

    master

    An Action is an object dispatched to a Zedux store to trigger state changes. Every action must contain a type property of type string. It may optionally include a payload for data and meta for additional metadata.

    Conceptually, actions are a subset of ActionChains; an Action is simply an ActionChain with a size of 1.

    export interface Action<
      Payload = any,
      Type extends string = string,
      Meta = any
    > {
      meta?: Meta
      payload?: Payload
      type: Type
    }
  7. What is an AtomSelector?

    master

    An AtomSelector is a function used to derive state from atoms. It is a blueprint for pulling data and does not execute until it is called by a consumer. It receives an AtomGetters object as its first parameter, which allows it to retrieve atom values and compose other selectors.

    Common ways to call an AtomSelector:

    • useAtomSelector() (React hook)
    • injectAtomSelector() (Injector)
    • ecosystem.select() (Ecosystem method)
    • The select function within another AtomSelector (Composition)

    When to use AtomSelectors:

    • Dynamically registering graph edges in components.
    • Extracting specific parts of an atom instance's state.
    • Performing simple calculations that do not require memoization.

    When NOT to use AtomSelectors:

    AtomSelectors are not atoms and cannot use injectors. Use an Ion instead if you need:

    • Memoization: Use an atom with injectMemo().
    • Store management: Use an atom with injectStore().
    • Side effects: Use an atom with injectEffect().
    • Promises/Suspense: Use AtomApi#setPromise() in an atom.
    type AtomSelector<T = any, Args extends any[] = []> = (
      getters: AtomGetters,
      ...args: Args
    ) => T
  8. What is an Ecosystem in Zedux

    master

    An Ecosystem is an isolated atom environment. It acts as a container that manages the lifecycle and relationships of atoms and selectors. Every ecosystem provides:

    • A scheduler for running atom-related tasks intelligently.
    • A graph to manage atom dependencies.
    • A Selectors class instance for managing cached Atom Selector instances.
    • An id generator for unique IDs for unnamed selectors and external graph nodes.

    Ecosystems can be used independently of React, making them ideal for testing atoms and selectors in isolation.

  9. Use Atom APIs to pass state, exports, and promises

    master

    The Atom API is a standardized container used to pass the three core "meta data types" of an atom between injectors and state factories:

    1. State: Usually contained within store objects.
    2. Exports: Functions or values exported by the atom.
    3. Promises: The atom's resolution promise.

    You can construct and manipulate these using the api() utility. This pattern is used by built-in injectors like injectPromise().

    // Constructing an Atom API
    const myApi = api(myStore).setExports(myExports).setPromise(myPromise)
    
    // Accessing the components
    const { exports, promise, store } = myApi
  10. Use Ions for expensive state derivations

    master

    While Atom Selectors are great for simple, inexpensive logic, they lack fine-grained control over re-evaluation. For complex, expensive operations (like sorting or filtering large lists), use Ions.

    Ions are special atoms created with the ion() factory. They receive an AtomGetters object as their first parameter, allowing them to behave like atoms while being specifically designed for selector-type operations.

    When to use an Ion instead of an Atom Selector:

    • To memoize expensive calculations.
    • To run side effects on state change.
    • To trigger React Suspense.
    • When you need any other atom-specific capabilities.
    import { ion } from '@zedux/react'
    
    // An ion that filters and sorts users based on a role
    const sortedUsersAtom = ion('sortedUsers', ({ get }, roleFilter: string) => {
      const users = get(usersAtom).filter(user => user.role === roleFilter)
      return [...users].sort((userA, userB) => userA.name.localeCompare(userB.name))
    })
    
    function MyComponent() {
      // Access ions just like regular atoms
      const adminUsers = useAtomValue(sortedUsersAtom, ['admin'])
    }
  11. How Zedux plugins work

    master

    Plugins in Zedux are low-level tools used to implement active control over state flow. Unlike stores, which use passive effects subscribers, plugins hook into the ecosystem level.

    They communicate via a bidirectional stream:

    1. The Ecosystem to Plugin: The ecosystem dispatches "mod events" (special Action objects) via a modBus (which is itself a Zedux store).
    2. The Plugin to Ecosystem: The plugin communicates its requirements via a modStore (also a Zedux store). By updating the modStore with specific mod names, the plugin tells the ecosystem which internal events it wants to receive.

    Ecosystems disable most mod events by default for performance. A plugin must explicitly request them to receive them.

  12. Expose a store from an atom

    master

    By default, Zedux automatically creates a store for every atom. If you want an atom to use a specific store you created via injectStore, you must return the store from the atom's state factory.

    Returning the store tells Zedux: "Don't create a store for me; use this one instead." This allows for joint updates: the atom can update its state internally (via side effects) and externally (via the setState function returned by useAtomState in a component).

    const greetingAtom = atom('greeting', () => {
      const store = injectStore('Hello, World!')
    
      return store // Returning the store exposes it to consumers
    })
    
    function Greeting() {
      const [state] = useAtomState(greetingAtom)
      return <div>{state}</div>
    }