A reactive state management and UI framework for React
npm install plug-codetsx
// From this mess... š°
const [users, setUsers] = useState([]);
const [filteredUsers, setFilteredUsers] = useState([]);
const [loading, setLoading] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
useEffect(() => {
const filtered = users.filter(u =>
u.name.includes(searchQuery) || u.email.includes(searchQuery)
);
setFilteredUsers(filtered);
}, [users, searchQuery]);
// To this elegance āØ
api.filterStore('users', 'filteredUsers', searchQuery,
['name', 'email'],
{ debounce: 300, useWebWorker: 'auto' }
);
const users = useStore('filteredUsers');
`
⨠Features That Make You Smile
$3
- Web Workers for heavy operations
- Built-in virtualization for 100k+ items
- Smart caching and memoization
- React 18 concurrent features
$3
- Plugin architecture out of the box
- Isolated feature modules
- Dynamic loading support
- Zero coupling between features
$3
- Slot-based composition
- Middleware for everything
- Priority-based rendering
- Component wrapping & injection
$3
- Full TypeScript inference
- Auto-completion everywhere
- Catch errors at compile time
- No any types needed
š¬ Quick Start
$3
`tsx
import { createSimplePlugC } from 'plugc';
const { Provider, useStore, useAction } = createSimplePlugC({
initialState: { count: 0 },
actions: {
increment(draft) { draft.count++ },
decrement(draft) { draft.count-- }
}
});
function Counter() {
const count = useStore(s => s.count);
const increment = useAction('increment');
return ;
}
function App() {
return ;
}
`
That's it! No boilerplate, no configuration files, no headaches.
$3
`tsx
import { createPlugC } from 'plugc';
type AppSchema = {
stores: {
todos: Todo[];
user: User | null;
};
commands: {
'todos:add': { payload: string; result: Todo };
};
slots: {
'app.sidebar': { collapsed: boolean };
};
};
const { api, SystemPlcRoot, useStore, useCommand } = createPlugC();
// Type-safe, autocomplete-friendly, beautiful šØ
`
šŖ Real-World Examples
$3
`tsx
// Handle 50,000 products like a boss šŖ
const ProductCatalog = () => {
const [search, setSearch] = useState('');
// Automatic web worker processing for large datasets
api.filterStore(
'allProducts', // 50,000 items
'searchResults', // Filtered output
search,
['name', 'description', 'sku'],
{
debounce: 300,
useWebWorker: 'auto', // Magic! āØ
onProgress: (done, total) => console.log(${done}/${total})
}
);
const results = useStore('searchResults');
return ;
};
`
$3
`tsx
// Render 100,000 items smoothly š
api.markVirtual('message-list', {
itemHeight: 80,
overscan: 10
});
api.register('message-list', 'message-item', ({ message }) => (
));
function ChatWindow() {
const messages = useStore('messages'); // 100k+ items
const renderMessages = useSlot('message-list');
return (
{renderMessages({ items: messages })}
);
}
`
$3
`tsx
// Install features like plugins
const DarkModePlugin = {
name: 'dark-mode',
state: { enabled: false },
commands: {
toggle: () => {
api.setSubstore('dark-mode', 'enabled', (draft) => !draft);
}
},
slots: {
'app.settings': [{
id: 'dark-mode-toggle',
component: DarkModeToggle,
priority: 100
}]
}
};
api.registerModule(DarkModePlugin);
// Later, load more features dynamically
await api.loadFeature(() => import('./plugins/analytics'));
await api.loadFeature(() => import('./plugins/notifications'));
`
$3
`tsx
// Transform data like a pro šÆ
api.makeTransform('user-data', 'validate', (data) => {
if (!data.email) throw new Error('Email required');
return data;
}, 0);
api.makeTransform('user-data', 'normalize', (data) => ({
...data,
email: data.email.toLowerCase(),
name: data.name.trim()
}), 10);
api.makeTransform('user-data', 'enrich', async (data) => {
const avatar = await fetchAvatar(data.email);
return { ...data, avatar };
}, 20);
// Process through the pipeline
const user = await api.getTransform('user-data', rawUserInput);
`
šÆ Choose Your Adventure
I want to...
Use this
Build a simple app quickly
Simple Mode
Build a complex, scalable app
Advanced Mode
Filter huge datasets
filterStore()
Render massive lists
Virtualization
Build a plugin system
Module System
Compose flexible UIs
Slots
Process data pipelines
Transforms
š Performance Benchmarks
`
Rendering 10,000 items:
āā PlugC (virtualized): ~16ms ā
āā Regular React: ~450ms ā ļø
āā With useMemo: ~180ms š
Filtering 50,000 items:
āā PlugC (web workers): ~45ms ā
āā Array.filter (main): ~320ms ā ļø
āā Lodash: ~280ms š
State updates (1000 subscribers):
āā PlugC: ~8ms ā
āā Redux: ~35ms š
āā Context API: ~120ms ā ļø
`
š§ Core Concepts in 30 Seconds
`tsx
// 1ļøā£ STORES - Your state lives here
api.createStore('todos', []);
api.setStore('todos', (draft) => { draft.push(newTodo) });
const todos = useStore('todos');
// 2ļøā£ COMMANDS - Your business logic
api.registerCommand('fetchUsers', async () => {
const users = await fetch('/api/users').then(r => r.json());
api.setStore('users', users);
});
await api.execute('fetchUsers');
// 3ļøā£ SLOTS - Composable UI pieces
api.register('sidebar', 'user-menu', UserMenu, 100);
api.register('sidebar', 'notifications', Notifications, 90);
const renderSidebar = useSlot('sidebar');
// 4ļøā£ WATCHERS - React to changes
api.watch('user', u => u?.id, (newId, oldId) => {
console.log(User changed: ${oldId} ā ${newId});
});
// 5ļøā£ DERIVES - Computed values
api.deriveStore('total', 'cart', ['cart', 'products'],
(cart, products) => calculateTotal(cart, products)
);
`
šØ Beautiful Developer Experience
$3
`tsx
// TypeScript knows everything! š§āāļø
const count = useStore('counter'); // ā number
const user = useStore('user'); // ā User | null
const invalid = useStore('notExist'); // ā Type error!
await api.execute('login', credentials); // ā Returns User
await api.execute('login', 123); // ā Type error!
`
$3
`tsx
const { api } = createSimplePlugC({
initialState: { / ... / },
actions: { / ... / },
options: { debug: true } // š Detailed logging
});
`
š¦ Installation
`bash
npm install plugc immer
`
`bash
yarn add plugc immer
`
`bash
pnpm add plugc immer
`
š Changelog
$3
#### š New Features
- š Enhanced connect() API: Now supports custom selectors for fine-grained reactivity
`tsx
const UserDashboard = api.connect(
['user', 'todos:items'],
(user, todos) => ({ userName: user?.name, count: todos.length }),
({ userName, count }) => {userName} has {count} todos
);
`
- ā” connectSimple() Method: Lightweight connection without selectors for simple use cases
`tsx
const AutoSaver = api.connectSimple(
['todos:items'],
() => {
const todos = api.getSubstore('todos', 'items');
useEffect(() => localStorage.setItem('todos', JSON.stringify(todos)), [todos]);
return null;
}
);
`
- š£ New React Hooks:
- useConnect() - Hook version of connect() for inline usage
- useConnectSimple() - Hook version of connectSimple()
`tsx
const { useConnect } = createPlugC();
const Dashboard = useConnect(
['user', 'settings'],
(user, settings) => ({ name: user.name, theme: settings.theme }),
({ name, theme }) => Hello {name}
);
`
- š Native Filtering System: Built-in filterStore() with web worker support
- Automatic web worker delegation for large datasets
- Configurable debouncing and matching strategies
- LRU caching for improved performance
- Progress callbacks for better UX
`tsx
api.filterStore('products', 'filtered', searchQuery, ['name', 'sku'], {
debounce: 300,
useWebWorker: 'auto',
onProgress: (done, total) => setProgress(done / total)
});
`
#### š Bug Fixes
- Fixed type inference issues in nested substores
- Resolved memory leaks in watch/unwatch cycles
- Corrected virtual scrolling position calculations
- Fixed race conditions in async transform pipelines
#### š§ Improvements
- Stricter TypeScript definitions in both Simple and Advanced modes
- Better type inference for command payloads and results
- Enhanced autocomplete for slot names and props
- Improved error messages with clearer debugging information
- Optimized re-render performance for large dependency arrays
#### š„ Breaking Changes
None - this release is fully backward compatible!
---
šÆ Quick Comparisons
$3
`tsx
// Redux
const INCREMENT = 'INCREMENT';
const increment = () => ({ type: INCREMENT });
const reducer = (state = 0, action) =>
action.type === INCREMENT ? state + 1 : state;
const store = createStore(reducer);
// + middleware setup, provider, selectors...
// PlugC
const { api } = createSimplePlugC({
initialState: { count: 0 },
actions: { increment: (draft) => { draft.count++ } }
});
`
$3
`tsx
// Zustand
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 }))
}));
// PlugC (Simple Mode)
const { useStore, useAction } = createSimplePlugC({
initialState: { count: 0 },
actions: { increment: (draft) => { draft.count++ } }
});
// BUT PlugC also gives you:
// ā
Slots for UI composition
// ā
Built-in virtualization
// ā
Web workers for filtering
// ā
Data pipelines
// ā
Module system
// ā
And more...
`
$3
`tsx
// Atoms everywhere
const countAtom = atom(0);
const doubleAtom = atom((get) => get(countAtom) * 2);
const usersAtom = atom([]);
// ...manage dozens of atoms
// PlugC - centralized, organized
const { api } = createPlugC({
initialState: {
count: 0,
users: []
}
});
api.deriveStore('double', 'computed', ['count'],
(count) => count * 2
);
`
---
$3
`bash
npm install plugc
``