Detalhes do pacote

state-jet

Ultra-lightweight global state management for React

react, state, redux, state-management

readme (leia-me)

npm npm GitHub issues

A zero-boilerplate, ultra-fast global state management library for React.

For more details, see here.

Table of Contents

Why state-jet

  • No Context, No Providers – Works outside React, reducing unnecessary re-renders.
  • Automatic Re-Renders – Only components using specific state values update.
  • Super Lightweight – Ultra small!
  • SSR & Next.js Support – Works on both client and server.

Documentation

Documentation: https://statejet.org/docs

Tutorials: https://statejet.org/docs/tutorial/intro/

API Reference: https://statejet.org/docs/api-reference/global-state/

Installation

The Statejet package lives in npm. Please see the installation guide.

To install the latest stable version, run the following command:

npm install state-jet

Or if you're using yarn:

yarn add state-jet

Or if you're using cdn:

<script src="https://cdn.jsdelivr.net/npm/state-jet@latest/dist/index.cjs"></script>

Wiki

Ask DeepWiki

GlobalState

The useStateGlobal hook is the simplest entry point to State-Jet—-ideal for simple applications with minimal state management needs. It allows you to create stateful values that can be accessed and updated from any component in your application, regardless of their location in the component tree.

Create GlobalState

// file: src/store/index.ts

import { useStateGlobal } from "state-jet";

export const counterState = useStateGlobal("counter", 0);

Binding Global State to a Component

// file: src/components/Counter.tsx

import { counterState } from "../store";

export default function Counter() {
  const count = counterState.useState() as number;

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => counterState.set(count - 1)}>Decrement</button>
      <button onClick={() => counterState.set(count + 1)}>Increment</button>
    </div>
  );
}

Slices

Slices in state-jet represent logical groupings of state that help organize application data into manageable pieces.

Create Slice

// file: src/store/slices.ts

import { useSlice } from "state-jet";

const cartSlice = useSlice("cart");

export const useCartSlice = () => cartSlice("cartState", {});

Multi States in Single Slice

// file: src/store/slices.ts

import { useSlice } from "state-jet";

const productSlice = useSlice("products");
const cartSlice = useSlice("cart");

// Define multiple state values under a slice
export const useProductSlice = () => ({
  productState: productSlice("productState", {}),
  productFilter: productSlice("productFilter", { search: "", category: "all" }),
  productSort: productSlice("productSort", { order: "asc" }),
});
export const useCartSlice = () => cartSlice("cartState", {});

Store

The useStore hook serves as a mechanism to group related slices of state into a cohesive store, enabling modular and organized state management in React applications which are better suited for larger applications with more complex and structured state requirements.

Create Store

// file: src/store/index.ts

import { useStore } from "state-jet";
import { useProductSlice, useCartSlice } from "./slices";

/**
 * Ecommerce store with product and cart slices
 */
const initializer: any = () => ({
  products: useProductSlice(),
  cart: useCartSlice(),
});

export const useEcommerceStore = () =>  useStore(initializer);

Binding Store to a Component

// file: src/components/ProductList.tsx

import { useEcommerceStore } from "../store";

type ProductType = {
  name: string,
  price: number
}

type CartType = {
  name: string,
  price: number,
  count: number
}

export const ProductList = () => {
  const store = useEcommerceStore();
  const { productState }: any = store.products;
  const cart: any = store.cart;
  const productSliceData: any = productState.useState();
  const cartSliceData: any = cart.useState();
  const productItems: Array<ProductType> = productSliceData?.items || [];
  const cartItems: Array<CartType> = cartSliceData?.items || [];

  const addToCart = (product: ProductType) => {
    if (cartItems.some((cartItem: CartType) => cartItem.name === product.name)) {
      cart.set((cartVal: any)=> ({
        ...cartVal,
        items: cartItems.map((cartItem: CartType) => {
          if (cartItem.name === product.name) {
            return { ...cartItem, count: (cartItem.count || 0) + 1 };
          }
          return cartItem;
        })
      }));
    } else {
      cart.set((cartVal: any)=> ({
        ...cartVal,
        items: [...cartItems, { ...product, count: 1 }]
      }));
    }
  };

  return (
    <div>
      <h2>🛍️ Products</h2>
      <ul>
        {productItems && productItems.map((productItem: ProductType, index: number) => (
          <li key={index}>
            {productItem.name} - ${productItem.price}{" "}
            <button onClick={() => addToCart(productItem)}>Add to Cart</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

Middlewares

Middleware in state-jet is a powerful mechanism for intercepting, transforming, and processing state updates before they are applied to the store.

Unlike other libraries, you do not need to rely on any external dependencies. A middleware property from options helps to add middleware for state-jet.

function useStateGlobal<T>(
  ...
  options?: { middleware?: [] }
)

Logger Middleware

You can log your store for every action.

// file: src/store/middleware.ts

export const loggerMiddleware = (key: string, prev: number, next: number) => {
  console.log(`[state-jet] ${key}: ${prev}${next}`);
};

Create global state with loggerMiddleware

// file: src/store/index.ts

import { useStateGlobal } from "state-jet";
import { loggerMiddleware } from "./middleware";

export const counterState = useStateGlobal("counter", 0, { middleware: [loggerMiddleware] });

Binding Global State to a Component

// file: src/components/Counter.tsx

import { counterState } from "../store";

export default function Counter() {
  const count = counterState.useState() as number;

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => counterState.set(count - 1)}>Decrement</button>
      <button onClick={() => counterState.set(count + 1)}>Increment</button>
    </div>
  );
}

Reducer Middleware

Can't live without reducer? No worries, StateJet supports reducer middleware.

// file: src/store/middleware.ts

type Action<T> = { type: string; payload?: T };
type Middleware<T> = (
  key: string,
  prev: T,
  next: T | Action<T> | any,
  set?: (value: T) => void,
) => T | void | Promise<void>;

export const reducerMiddleware: Middleware<number> = (key, prev, action: Action<any>) => {
  switch (action.type) {
    case "INCREMENT":
      return prev + 1;
    case "DECREMENT":
      return prev - 1;
    case "RESET":
      return 0;
    default:
      return prev;
  }
}

Create global state with reducerMiddleware

// file: src/store/index.ts

import { useStateGlobal } from "state-jet";
import { reducerMiddleware } from "./middleware";

export const counterState = useStateGlobal("counter", 0, { middleware: [reducerMiddleware] });

Binding Global State to a Component

// file: src/components/Counter.tsx

import { counterState } from "../store";

export default function Counter() {
  const count = counterState.useState() as number;

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => counterState.set({ type: "DECREMENT" })}>Decrement</button>
      <button onClick={() => counterState.set({ type: "INCREMENT" })}>Increment</button>
      <button onClick={() => counterState.set({ type: "RESET" })}>Reset</button>
    </div>
  );
}

Debounce Middleware

You can delay the update of global state.

// file: src/store/middleware.ts

let timer: ReturnType<typeof setTimeout>;

// Debounce middleware with delay
export const debounceMiddleware = (delay: number) => {
    return (key: string, prev: number, next: any, set?: (value: any) => void) => {
        clearTimeout(timer);
        if (set) {
          timer = setTimeout(() => {
            console.log(`[state-jet] Debounced: ${key}${next}`);
            set(next); // Apply the debounced update
          }, delay);
        }
    };
};

Create global state with debounceMiddleware

// file: src/store/index.ts

import { useStateGlobal } from "state-jet";
import { debounceMiddleware } from "./middleware";

export const counterState = useStateGlobal("counter", 0, { middleware: [debounceMiddleware(500)] });

Optimistic Middleware

You can optimistically update global state with rollback support.

// file: src/store/middleware.ts

export const optimisticMiddleware = (apiUrl: string) => {
  return async (key: string, prev: number, next: number, set: any) => {
    set(next); // Optimistically update state

    try {
      await fetch(apiUrl, {
        method: "POST",
        body: JSON.stringify({ key, value: next }),
        headers: { "Content-Type": "application/json" },
      });
    } catch (error) {
      console.warn(`[state-jet] Rollback: Failed to sync ${key}`);
      set(prev); // Rollback state on failure
    }
  };
};

Create global state with optimisticMiddleware

// file: src/store/index.ts

import { useStateGlobal } from "state-jet";
import { optimisticMiddleware } from "./middleware";

export const profileState = useStateGlobal("profile", { name: "John" }, { 
  middleware: [optimisticMiddleware("/update-profile")],
});

Custom Middleware

You can also create your own custom middleware in state-jet.

// file: src/store/middleware.ts

export const validateAgeMiddleware = (key: string, prev: number, next: number) => {
  if (next < 0) {
    console.warn("Age cannot be negative!");
    return prev;
  }
  return next;
};

Create global state with validateAgeMiddleware

// file: src/store/index.ts

import { useStateGlobal } from "state-jet";
import { validateAgeMiddleware } from "./middleware";

export const ageState = useStateGlobal("age", 0, { middleware: [validateAgeMiddleware] });

Binding Global State to a Component

// file: src/components/Profile.tsx

import { ageState } from "../store";

export default function Profile() {
  const age = ageState.useState() as number;

  return (
    <div>
      <h1>Age: {age}</h1>
      <button 
        onClick={() => {
          ageState.set(-5) // Age will be 0 eventhough it updated with negative value due to middleware logic
        }}>
          Set negative
      </button> 
    </div>
  );
}

A more complete middleware usage is here.

Typescript Usage

Here is the example for creating global state with typescript definition.

interface Todo = {
  id: number;
  text: string;
  completed: boolean
};

const todoState = useStateGlobal<Todo[]>("todos", []);

Why state-jet Is More Advanced Than Zustand

  • No Proxies Needed: Zustand uses proxies for state updates, but state-jet uses signals, making it even faster.
  • Derived State Is Automatic: No need for selectors; state updates only trigger where necessary.
  • Optimistic Updates & Rollback: Unlike Zustand, state-jet has built-in support for instant UI updates and auto-revert on failures.
  • Multi-Tab Sync: Global state persists across browser tabs and devices.
  • CRDT Support: Automatic conflict resolution for real-time apps, something even Zustand lacks.

FAQ

  • If you want to manage your global state like useState as usual.
  • If you want to manage your global state without involving in setting up Provider Component, Dispatcher, Reducer, etc.
  • If you want to see Redux or Context API alternative.

Conclusion

If you need the simplest, fastest, and most advanced state management solution for React, state-jet beats Redux, Recoil, MobX, Jotai, and even Zustand in performance, reactivity, and developer experience 🚀.

Comparison Table

Feature Redux Recoil MobX Jotai Zustand state-jet
Easy Setup ❌ No ❌ No ⚠️ No ❌ No ⚠️ Minimal ✅ Ultra-Minimal
Bundle Size 🚀 Large 🚀 Medium ⚡ Small ⚡ Small ⚡ Small 🔥 Ultra-Small
Reactivity ⚠️ Reducers ✅ Atoms ✅ Proxy-Based ✅ Signals ✅ Proxy-Based ✅ Signal-Like
Renders Only Affected ❌ No ✅ Yes ✅ Yes ✅ Yes ✅ Yes ✅ Yes
Derived/Computed State ❌ No ✅ Yes ✅ Yes ✅ Yes ⚠️ Manual Selectors ✅ Yes (Automatic)
Optimistic Updates ❌ No ❌ No ❌ No ❌ No ⚠️ Requires Middleware ✅ Built-in
Undo/Redo ❌ No ❌ No ❌ No ❌ No ⚠️ Requires Middleware ✅ Built-in
CRDT Conflict Resolution ❌ No ❌ No ❌ No ❌ No ❌ No ✅ Yes

Comparison with other libraries

Contributing

Development of State-jet happens in the open on GitHub, and we are grateful to the community for contributing bugfixes and improvements. Read below to learn how you can take part in improving State-jet.

Publishing

Before pushing your changes to Github, make sure that version in package.json is changed to newest version. Then run npm install for synchronize it to package-lock.json and pnpm install for synchronize it to pnpm-lock.yaml

Feedbacks and Issues

Feel free to open issues if you found any feedback or issues on state-jet. And feel free if you want to contribute too! 😄

License

State-jet is MIT licensed.

changelog (log de mudanças)

Changelog

All notable changes to this project will be documented in this file. See standard-version for commit guidelines.

2.2.4 (2025-11-07)

2.2.3 (2025-11-06)

2.2.2 (2025-11-02)

2.2.1 (2025-10-30)

Bug Fixes

  • rebrand state-jet with new logo color (1f5a68c)

2.2.0 (2025-10-30)

Features

  • rebrand state-jet with new logo and domain (ff1afd5)

2.1.6 (2025-10-30)

2.1.5 (2025-10-29)

Bug Fixes

  • remove deepwiki github actions (f44ee6b)

2.1.4 (2025-10-29)

Bug Fixes

  • modify support of deepwiki with github actions (74cc89a)

2.1.3 (2025-10-29)

Bug Fixes

  • modify support of deepwiki with github actions (0b24b23)

2.1.2 (2025-10-29)

Bug Fixes

  • modify support of deepwiki with github actions (0504ab7)

2.1.1 (2025-10-29)

Bug Fixes

  • modify support of deepwiki with github actions (1d6cc78)

2.1.0 (2025-10-29)

Features

  • adding support of deepwiki with github actions (a96d3db)

2.0.26 (2025-10-27)

2.0.25 (2025-10-27)

2.0.24 (2025-10-23)

Documentation

  • adding support for multistate website (54c73fc)

2.0.23 (2025-10-23)

Documentation

  • adding support of mulistate in slice with updated readme (0d3808a)

2.0.22 (2025-10-23)

Documentation

  • adding support of mulistate in slice (774088e)

2.0.21 (2025-06-24)

Documentation

2.0.20 (2025-06-23)

Documentation

2.0.19 (2025-06-23)

Documentation

2.0.18 (2025-06-23)

Documentation

  • updating website and readme (6a6b7ac)

2.0.17 (2025-06-23)

Documentation

  • updating website and readme (fcb68f7)

2.0.16 (2025-06-08)

Documentation

  • updating mobile deprecation changes (88d9215)

2.0.15 (2025-06-04)

Chores

  • solving security vulnerabilities (0b5e506)

2.0.14 (2025-06-04)

Documentation

  • updating changes for bench marks (8ba3446)

2.0.13 (2025-06-04)

Bug Fixes

  • updating get function and husky support (2c11f42)

2.0.12 (2025-05-29)

Documentation

  • updating changes for readme globalstate (5ff9a2b)
  • updating changes for readme globalstate (f6430ae)

2.0.11 (2025-05-29)

Documentation

  • updating changes for readme and examples (3b9f233)

2.0.10 (2025-05-29)

Bug Fixes

  • updating slice to support multi state (cae6aef)
  • updating slice to support multi state (1551d87)

2.0.9 (2025-03-27)

Documentation

  • updating changes for readme and website (a651ad1)

2.0.8 (2025-03-27)

Documentation

  • updating doc for store and slices (e470877)

2.0.7 (2025-03-27)

Documentation

  • updating readme and website (f1107dd)

2.0.6 (2025-03-24)

Documentation

  • updating codesandbox image and readme (a5d46e1)
  • updating codesandbox image and readme (3f04ef4)

2.0.5 (2025-03-24)

Documentation

  • updating doc to support useStore in ecommerce app (3cae7ed)

2.0.4 (2025-03-24)

Bug Fixes

  • updating useStore to work properly (7123291)

2.0.3 (2025-03-23)

Documentation

  • updating doc and example for v2 (379b6ea)

2.0.2 (2025-03-23)

Documentation

  • updating doc and example for v2 (d72cdff)

2.0.1 (2025-03-23)

Chores

1.4.0 (2025-03-23)

Features

  • supporting slices and store in stateJet (c2a7def)

1.3.1 (2025-03-17)

Documentation

  • update statejet document for middleware (1a63f4c)

1.3.0 (2025-03-17)

Features

  • setInterval fix for store file (9809336)

1.2.7 (2025-03-11)

Chores

  • consume latest library changes (6808f0b)

1.2.6 (2025-03-11)

Bug Fixes

  • consume latest library changes (45dd490)

1.2.5 (2025-03-11)

Bug Fixes

  • store middlware changes (9890177)

1.2.4 (2025-03-10)

Testing

  • adding test cases for statejet (10151d3)

1.2.3 (2025-03-09)

Chores

  • update package json in example folder (387f36c)

1.2.2 (2025-03-09)

Bug Fixes

  • changing readMe for support comparision table properly (bd4b869)

1.1.0 (2025-03-09)

Features

  • changing derived state function and adding support for prettier (db27de1)
  • changing derived state function and adding support for prettier (09cee58)
  • changing derived state function and adding support for prettier (6f8f7f3)
  • supporting advanced features (c18f1a8)

Chores

Changelog

All notable changes to this project will be documented in this file. See standard-version for commit guidelines.

(2025-03-09)

Features

  • changing derived state function and adding support for prettier (09cee58)
  • changing derived state function and adding support for prettier (6f8f7f3)