state-ref AI Agent Skills
Document Version: {{version}}
Additional materials (optional):
- •constraints/ (rules, mistakes, troubleshooting)
- •reference/ (watch, store creation, framework connectors)
- •examples/ (quick examples)
Activation Condition (Read First)
These guidelines apply only when state-ref is installed in the current project.
Before following this document:
- •Check
package.jsonforstate-refin dependencies/devDependencies - •Check
node_modules/state-refexists - •Check existing code imports from
state-ref
If state-ref is not installed, use the project's existing conventions. Do not suggest adding state-ref unless the user asks.
Core Rules (Keep In Memory)
- •Create stores with
createStore<T>(initialValue)for auto-sync mode. - •Access values via
.valueproperty onStateRefStoreproxies. - •Subscribe with
watch(callback)- callback receives(stateRef, isFirst). - •Subscription callbacks run once initially to collect dependencies.
- •Only tracked
.valuereads inside callbacks trigger re-runs on change. - •Use
AbortController.signalreturned from callback to unsubscribe. - •Use
createStoreManualSync()for Flux-like patterns withupdateRefandsync(). - •Framework connectors:
connectReact,connectPreact,connectVue,connectSvelte,connectSolid. - •Combine watches with
combineWatch([watch1, watch2] as const). - •Derive values with
createComputed([watches], callback). - •Use
copyable()for manual copy-on-write updates. - •Avoid mutating state directly; always assign via
.value. - •When unsure, check
node_modules/state-ref/dist/index.d.ts.
Common Mistakes & Fixes
Always access values via .value
ts
// BAD const age = stateRef.john.age; // GOOD const age = stateRef.john.age.value;
Track dependencies inside subscription callback
ts
// BAD - accessing .value outside callback won't track
const externalRef = watch();
watch((ref) => {
console.log(externalRef.count.value); // NOT tracked
});
// GOOD - use the callback's ref parameter
watch((ref) => {
console.log(ref.count.value); // Tracked
});
Use AbortController for cleanup
ts
const controller = new AbortController();
watch((ref) => {
console.log(ref.value);
return controller.signal;
});
controller.abort(); // Unsubscribe
Quick Examples
Example 1: Basic Store and Subscription
ts
import { createStore } from 'state-ref';
const watch = createStore({ count: 0, name: 'John' });
watch((ref, isFirst) => {
console.log('Count changed:', ref.count.value);
});
const ref = watch();
ref.count.value = 10; // Triggers subscription
Example 2: React Integration
ts
import { createStore } from 'state-ref';
import { connectReact } from '@stateref/connect-react';
const watch = createStore({ age: 20 });
export const useStore = connectReact(watch);
// In component
function Component() {
const { age } = useStore();
return <button onClick={() => age.value++}>{age.value}</button>;
}
Example 3: Manual Sync (Flux-like)
ts
import { createStoreManualSync } from 'state-ref';
const { watch, updateRef, sync } = createStoreManualSync({ count: 0 });
export const increment = () => {
updateRef.count.value += 1;
sync(); // Notify subscribers
};
Import Paths
- •Core:
import { createStore, createStoreManualSync, combineWatch, createComputed } from 'state-ref' - •Helpers:
import { lens, copyable, cloneDeep } from 'state-ref' - •React:
import { connectReact } from '@stateref/connect-react' - •Preact:
import { connectPreact } from '@stateref/connect-preact' - •Vue:
import { connectVue } from '@stateref/connect-vue' - •Svelte:
import { connectSvelte } from '@stateref/connect-svelte' - •Solid:
import { connectSolid } from '@stateref/connect-solid'
Summary
Use createStore for reactive state, access via .value, subscribe with watch(callback). Dependencies are tracked automatically inside callbacks. Use framework connectors for UI integration. For Flux patterns, use createStoreManualSync. Combine watches with combineWatch or derive computed values with createComputed.