Harlem State Management

website·Indexed 32 days ago

https://harlemjs.com/

A global state management solution for Vue 3 featuring a functional API for creating, reading, and mutating state. Harlem provides core concepts such as stores, state, getters, actions, and mutations, and is extensible via a system of plugins and extensions including official tools for SSR, Devtools, storage, and transactions.

Tokens
11.6K
Snippets
62
Records
84
Agent score
65%

What's inside Harlem

  1. Overview of Harlem state management for Vue 3

    Harlem is a lightweight, dependency-free global state management solution designed for Vue 3 projects of all sizes. It provides a single source of truth for global state, exposing state immutably and requiring changes to be made through auditable gateways (actions or mutations). This architecture prevents bugs associated with global mutable state, making applications more scalable and easier to debug compared to using simple global reactive objects.
  2. Overview of Harlem Extensions

    Extensions in Harlem are per-store additions used to add features, modify store behavior, or perform low-level tasks. They are the primary mechanism for extending the core functionality of a Harlem store.
  3. Organize Harlem store file structures

    Harlem is unopinionated about file structure. Common patterns include a 'Single file structure' (grouping all getters, mutations, and actions into single files per store) or a 'Multi-file structure' (splitting getters, mutations, and actions into their own directories with individual files).
    // store.js
    import STATE from './state';
    import { createStore } from '@harlem/core';
    
    export const {
        state,
        getter,
        mutation,
        ...store
    } = createStore('store1', STATE);
  4. Understand Harlem state management concepts

    Harlem uses a Redux-like state management pattern divided into four main concepts to manage data flow:

    • State: The single source of truth for data; it is read-only.
    • Getters: Computed derivations of state mutations; they are read-only.
    • Mutations: The primary mechanism for changing state (read/write).
    • Actions: Asynchronous methods used for batching mutations or handling API requests (async read/write).

    Unlike monolithic state trees, Harlem uses individual stores to create logical boundaries between disparate data. While mutations are foundational, they are optional when using actions, as actions can mutate state directly while remaining auditable by devtools.

  5. Understand the role of Mutations in Harlem

    Mutations are a foundational concept in Harlem used to enable actions, triggers, devtools, tracing, and plugin integration. However, they are not mandatory; you can author stores using only actions and still retain the benefits of triggers and devtools.
  6. Understand the difference between Harlem plugins and extensions

    Harlem uses two different mechanisms for extending functionality:

    • Plugins: Registered once globally per Harlem instance. They manage all stores within that instance (e.g., DevTools integration or SSR support).
    • Extensions: Registered per individual store. They extend the functionality and APIs available to a specific store and are the primary way to add features to Harlem.
  7. Create a basic Harlem plugin

    Harlem plugins use an architecture similar to Vue's plugin system. A plugin must be an object containing a name field for identification and an install method. The install method provides access to the app instance, an eventEmitter for reacting to store events (mutations, errors) or communicating with other plugins, and a stores Map containing all registered store instances. When using TypeScript, it is recommended to install harlem or @harlem/core as a devDependency and cast the plugin object as a HarlemPlugin for full type support.
    import type { HarlemPlugin } from 'harlem';
    
    export default {
        name: 'my-plugin',
        install(app, eventEmitter, stores) {
            // Your plugin logic here
        }
    } as HarlemPlugin;
  8. Create a custom Harlem extension

    A Harlem extension is a function that returns another function. This returned function takes a store instance as an argument and returns an object. The returned object is then merged into the store instance, allowing you to add new methods or functionality to the store.
    import type {
        InternalStore,
        BaseState,
    } from '@harlem/core';
    
    interface Options {
        option1: string;
        option2: number;
    }
    
    export default function resetExtension<TState extends BaseState>(options?: Options) {
        return (store: InternalStore<TState>) => {
            function doSomethingWithTheStore(input: string) {
                // implementation logic
            }
    
            return {
                doSomethingWithTheStore
            };
        };
    }
  9. Install and register the Harlem Trace Extension

    The Trace Extension allows for detailed auditing of state changes by tracing granular updates. To use it, install the @harlem/extension-trace package and include it in the extensions array when calling createStore.
    yarn add @harlem/extension-trace
    # or
    npm install @harlem/extension-trace
    import traceExtension from '@harlem/extension-trace';
    import { createStore } from 'harlem';
    
    const STATE = { firstName: 'Jane', lastName: 'Smith' };
    
    const { 
        state, 
        getter, 
        mutation, 
        startTrace, 
        stopTrace, 
        onTraceResult 
    } = createStore('example', STATE, {
        extensions: [
            traceExtension({
                autoStart: true,
                debug: true,
            })
        ]
    });