npm.io
0.4.1 • Published 3 weeks ago

reactivity-store

Licence
MIT
Version
0.4.1
Deps
3
Size
395 kB
Vulns
0
Weekly
0
Stars
16

RStore

Vue-inspired Reactive State Management for React

Deploy npm downloads

Bring Vue's reactivity system to React with zustand-like simplicity. Direct mutation, automatic UI updates - no manual subscriptions needed!

Documentation · Getting Started · Examples


Why RStore?

  • Direct Mutation - No setState, just mutate and UI updates automatically
  • Vue Reactivity - Use ref(), reactive(), computed() from @vue/reactivity
  • Zustand-like API - Clean, minimal API design
  • Built-in Middleware - Persist, actions, Redux DevTools out of the box
  • TypeScript First - Full type safety and excellent IntelliSense
  • Zero Boilerplate - No reducers, no dispatch, no manual subscriptions

Installation

npm install reactivity-store
# or
pnpm add reactivity-store

Quick Start

Vue Approach

For Vue developers or those wanting fine-grained reactivity:

import { createStore, ref, computed } from "reactivity-store";

const useCounter = createStore(() => {
  const count = ref(0);
  const doubled = computed(() => count.value * 2);

  const increment = () => count.value++; // Direct mutation!

  return { count, doubled, increment };
});

function App() {
  const { count, doubled, increment } = useCounter();
  return (
    <div>
      <p>Count: {count}</p>
      <p>Doubled: {doubled}</p>
      <button onClick={increment}>+1</button>
    </div>
  );
}
React Approach

For React developers who want simplicity without learning Vue APIs:

import { createState } from "reactivity-store";

const useCounter = createState(() => ({ count: 0 }), {
  withActions: (state) => ({
    increment: () => state.count++,
    decrement: () => state.count--,
  }),
});

function App() {
  const { count, increment, decrement } = useCounter();
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
    </div>
  );
}

Two Approaches, One Library

Vue Approach React Approach
Best for Vue developers React developers
APIs ref, reactive, computed Plain objects + actions
Features Auto-computed, lifecycle hooks Middleware: persist, DevTools
Use createStore createState

Built-in Middleware

Persistent State
const useSettings = createState(() => ({ theme: "light", language: "en" }), {
  withPersist: "app-settings", // Auto-saves to localStorage
  withActions: (state) => ({
    setTheme: (theme) => (state.theme = theme),
  }),
});
Redux DevTools
const useCounter = createState(() => ({ count: 0 }), {
  withNamespace: "Counter", // Shows up in Redux DevTools
  withActions: (state) => ({
    increment: () => state.count++,
  }),
});
Performance Options
const useStore = createState(() => ({ nested: { count: 0 } }), {
  withDeepSelector: true, // Track nested changes (default: true)
  withStableSelector: false, // Stable selector for performance
  withActions: (state) => ({
    increment: () => state.nested.count++,
  }),
});

Advanced Features

Lifecycle Hooks
import { createStoreWithComponent, ref, onMounted, onUnmounted } from "reactivity-store";

const Timer = createStoreWithComponent({
  setup: () => {
    const seconds = ref(0);
    let timer;

    onMounted(() => {
      timer = setInterval(() => seconds.value++, 1000);
    });

    onUnmounted(() => {
      clearInterval(timer);
    });

    return { seconds };
  },
});

function App() {
  return <Timer>{({ seconds }) => <div>{seconds}s</div>}</Timer>;
}
Component-local Reactive State
import { useReactiveState } from "reactivity-store";

function TodoList() {
  const [state, setState] = useReactiveState({
    todos: [],
    filter: "all",
  });

  const addTodo = (text) => {
    setState((s) => {
      s.todos.push({ id: Date.now(), text, done: false });
    });
  };

  return <div>{/* ... */}</div>;
}
State Subscriptions
const useCounter = createState(() => ({ count: 0 }), { withActions: (s) => ({ increment: () => s.count++ }) });

// Subscribe anywhere in your app
useCounter.subscribe(
  (state) => state.count,
  () => console.log("Count changed:", useCounter.getReadonlyState().count)
);

Comparison

Traditional React

const [count, setCount] = useState(0);

setCount((prev) => prev + 1);

RStore (Vue Approach)

const count = ref(0);

count.value++;

RStore (React Approach)

const useCount = createState(() => ({ count: 0 }), {
  withActions: (s) => ({
    increment: () => s.count++,
  }),
});

API Overview

API Purpose
createStore Vue-style reactive stores with ref(), reactive(), computed()
createState React-style state with actions and middleware
createStoreWithComponent Component-scoped stores with lifecycle hooks
useReactiveState Component-local reactive state (like useState but reactive)
useReactiveEffect Side effects with automatic dependency tracking

Documentation

Visit https://mrwangjusttodo.github.io/r-store/ for complete documentation:

License

MIT MrWangJustToDo

Keywords