0.1.0 โ€ข Published 9 months ago

@developedbyed/superstate v0.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
9 months ago

Superstate

A lightweight, framework-agnostic state management library inspired by Zustand.

Features

  • ๐Ÿฆ„ Simple API: Minimalist API that's easy to learn
  • ๐Ÿ”„ Immutable updates: State is updated immutably
  • ๐Ÿงช TypeScript-first: Built with TypeScript for excellent type inference
  • ๐Ÿงฉ Middleware support: Extend functionality with middleware
  • ๐Ÿ” Selective subscriptions: Subscribe to specific parts of your state
  • ๐ŸŒ Framework agnostic: Use with any framework or vanilla JavaScript

Installation

npm install @developedbyed/superstate

Quick Start

import { createStore } from "@developedbyed/superstate";

// Create a store
const useCounterStore = createStore((set, get) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}));

// Use the store
console.log(useCounterStore.getState().count); // 0

// Update the state
useCounterStore.getState().increment();
console.log(useCounterStore.getState().count); // 1

// Subscribe to state changes
const unsubscribe = useCounterStore.subscribe((state) =>
  console.log("State changed:", state)
);

// Later: unsubscribe when no longer needed
unsubscribe();

Middleware

Enhance your store with middleware:

import {
  createStore,
  applyMiddleware,
  logger,
  persist,
} from "@developedbyed/superstate";

const counterStore = createStore((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));

// Apply middleware
const enhancedStore = applyMiddleware(
  counterStore,
  logger, // Log all state changes
  persist("counter-store") // Save state to localStorage
);

// Now use enhancedStore instead of counterStore

Selecting Partial State

Subscribe to specific parts of your state for better performance:

import { createStore, select } from "@developedbyed/superstate";

const store = createStore(() => ({
  user: { name: "John", age: 30 },
  settings: { theme: "dark" },
  todos: [],
}));

// Subscribe only to the user slice
const userSelector = select(store, (state) => state.user);
userSelector((user) => {
  console.log("User changed:", user);
});

// This will trigger the above callback
store.setState({ user: { name: "Jane", age: 28 } });

// This won't trigger the callback
store.setState({ settings: { theme: "light" } });

Creating Custom Middleware

You can create your own middleware to extend functionality:

import {
  createStore,
  applyMiddleware,
  Middleware,
} from "@developedbyed/superstate";

// Create a throttle middleware
const throttle =
  (delay: number): Middleware =>
  (store) => {
    const originalSetState = store.setState;
    let lastCall = 0;
    let timeoutId: any = null;

    store.setState = (partial, replace) => {
      const now = Date.now();
      const remaining = delay - (now - lastCall);

      if (remaining <= 0) {
        lastCall = now;
        originalSetState(partial, replace);
      } else {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
          lastCall = Date.now();
          originalSetState(partial, replace);
        }, remaining);
      }
    };

    return store;
  };

// Use the custom middleware
const store = createStore(() => ({ count: 0 }));
const throttledStore = applyMiddleware(store, throttle(300));

TypeScript Usage

Superstate is built with TypeScript for excellent type inference:

import { createStore } from "@developedbyed/superstate";

interface TodoState {
  todos: Array;
  addTodo: (text: string) => void;
  toggleTodo: (id: number) => void;
  clearCompleted: () => void;
}

const useTodoStore = createStore((set, get) => ({
  todos: [],
  addTodo: (text) =>
    set((state) => ({
      todos: [...state.todos, { id: Date.now(), text, completed: false }],
    })),
  toggleTodo: (id) =>
    set((state) => ({
      todos: state.todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      ),
    })),
  clearCompleted: () =>
    set((state) => ({
      todos: state.todos.filter((todo) => !todo.completed),
    })),
}));

Integrating with React

While Superstate works with any framework, here's how to use it with React:

import { createStore } from '@developedbyed/superstate';
import { useState, useEffect } from 'react';

// Create a store
const counterStore = createStore((set) => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 })),
  decrement: () => set(state => ({ count: state.count - 1 })),
}));

// Create a custom hook
function useStore(
  store: { getState: () => T; subscribe: (listener: (state: T, prevState: T) => void) => () => void },
  selector: (state: T) => U
) {
  const [state, setState] = useState(() => selector(store.getState()));

  useEffect(() => {
    return store.subscribe((newState, oldState) => {
      const newSelectedState = selector(newState);
      const oldSelectedState = selector(oldState);

      if (newSelectedState !== oldSelectedState) {
        setState(newSelectedState);
      }
    });
  }, [store, selector]);

  return state;
}

// Use in component
function Counter() {
  const count = useStore(counterStore, state => state.count);
  const { increment, decrement } = counterStore.getState();

  return (

      Count: {count}
      +
      -

  );
}

License

MIT ยฉ developedbyed

0.1.0

9 months ago

0.0.2

9 months ago