reactivity-store
v0.4.0
Published
a reactive store, make you write reactive logic in react app just like zustand
Maintainers
Readme
🚀 RStore
Vue-inspired Reactive State Management for React
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-storeQuick 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:
- What is RStore?
- Why RStore?
- Vue Approach - createStore
- React Approach - createState
- Lifecycle Hooks
- Use Cases
License
MIT © MrWangJustToDo
