YASM is a lightweight state management library that simplifies data fetching and caching, with no external dependencies.
A lightweight state manager built on React hooks. No additional dependencies, no boilerplate code. Includes automatic localStorage persistence and real-time state synchronization.
// Before: useState
const [user, setUser] = useState(null);
useEffect(() => { fetchUser().then(setUser) }, []);
// After: YASM
const { data: user } = useData('user', fetchUser, '5m');
Show cached data instantly, fetch fresh data in background
const { data, isFromCache } = useData('posts', fetchPosts, '30s');
// Shows cached data immediately while fetching fresh data
Multiple components requesting same data = single network request
// Both components share the same request
function UserProfile() {
const { data } = useData('user-123', () => fetchUser(123));
}
function UserBadge() {
const { data } = useData('user-123', () => fetchUser(123)); // No duplicate request!
}
Human-readable intervals for real-time data
const { data: prices } = useData('customer-requests', fetchPrice, '10s'); // High frequency
const { data: metrics } = useData('dashboard', fetchMetrics, '30s'); // Moderate frequency
const { data: news } = useData('user-profile', fetchNews, '5m'); // Low frequency
Show cached data when requests fail
const { data, error, isFromCache } = useData('api/data', fetcher);
// Shows cached data when network requests fail
// Provides error information
// Maintains functionality with cached data
npm install yasm
# or
yarn add yasm
# or
pnpm add yasm
If you encounter this error:
Error: Cannot find module @rollup/rollup-win32-x64-msvc
Try one of these solutions:
- Use
pnpm
oryarn
instead of npm - Or with npm: Delete
node_modules
andpackage-lock.json
, then runnpm install
This is a known npm bug: npm/cli#4828
import { useData } from '@tobimadehin/yasm';
function UserProfile({ userId }) {
const {
data: user, // The fetched data
loading, // Loading state
error, // Error state
refresh, // Manual refresh function
isFromCache // Whether data is from cache
} = useData(
`user-${userId}`, // Cache key
() => fetchUser(userId), // Fetcher function
'5m' // Auto-refresh every 5 minutes
);
if (loading && !user) return <Skeleton />;
if (error && !user) return <Error error={error} />;
return (
<div>
<h1>{user.name}</h1>
{isFromCache && <Badge>Cached</Badge>}
{error && <Warning>Using cached data</Warning>}
<button onClick={refresh}>Refresh</button>
</div>
);
}
const { data } = useData('key', fetcher, '1m', {
revalidateOnFocus: true, // Refresh when window gains focus
revalidateOnReconnect: true, // Refresh when network reconnects
suspense: false, // Throw errors instead of returning them
initialData: [], // Initial data before first fetch
});
import { useData } from "@tobimadehin/yasm";
import {
YasmDebugMonitor,
} from 'yasm/debug';
function DevTools() {
const { data: prices } = useData(
'customer-requests',
fetchPrices,
'1s'
);
return (
<div>
<h3>Hello Yasm!</h3>
<YasmDebugMonitor />
</div>
);
}
Need additional control? You can bind keyboard shortcuts
import {
useCacheInspector,
useCacheMonitor
} from 'yasm/debug';
function DevTools() {
const { stats, hasFailures, isHealthy } = useCacheInspector();
const { show, hide, Monitor } = useCacheMonitor();
useEffect(() => {
const handleKeyPress = (e: KeyboardEvent) => {
// Ctrl/Cmd + Shift + M to show monitor
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'M') {
show();
}
// Ctrl/Cmd + Shift + H to hide monitor
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'H') {
hide();
}
};
window.addEventListener('keydown', handleKeyPress);
return () => window.removeEventListener('keydown', handleKeyPress);
}, [show, hide]);
return (
<div>
<button onClick={show}>Show Cache Monitor</button>
<Monitor />
{!isHealthy && <Alert>Cache issues detected</Alert>}
</div>
);
}
Note: Yasm Debug tools are automatically removed from production builds through tree-shaking in modern bundlers like Webpack, Rollup, and Vite
import { preload } from '@tobimadehin/yasm';
// Preload critical data
await preload('user-profile', fetchUser, '10m');
// In component - data is already available
const { data: user } = useData('user-profile', fetchUser, '10m');
YASM was built based on real-world feedback from developers building high-frequency applications. We welcome contributions!
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
MIT License - see the LICENSE file for details.
- Inspired by SWR, React Query, and real-world usage in production apps
- Built for developers who need simple, reliable caching without the complexity
- Tested in high-frequency trading dashboards, live sports apps, and real-time monitoring systems