Cache Feature Guide
What is Cache?
The cache feature in React Signify allows you to automatically save and restore your state values using the browser's storage (localStorage or sessionStorage). This means your data will persist even when users refresh the page or close and reopen your app.
Think of it like the browser "remembering" your app's state for you!
Why Use Cache?
Without cache:
// User sets theme to 'dark'
const sTheme = signify("light");
sTheme.set("dark");
// ❌ User refreshes page → theme resets to 'light'
With cache:
// User sets theme to 'dark'
const sTheme = signify("light", {
cache: { key: "user-theme" },
});
sTheme.set("dark");
// ✅ User refreshes page → theme stays 'dark'!
Basic Usage
Step 1: Enable Cache
Add a cache
configuration when creating your signify:
import { signify } from "react-signify";
const sUserPrefs = signify(
{
theme: "light",
language: "en",
},
{
cache: {
key: "user-preferences", // Unique name for this cache
},
}
);
Step 2: Use Normally
That's it! Your signify now automatically:
- Loads the saved value when your app starts
- Saves the value whenever it changes
function ThemeButton() {
const prefs = sUserPrefs.use();
const toggleTheme = () => {
sUserPrefs.set((prev) => {
prev.value.theme = prev.value.theme === "light" ? "dark" : "light";
});
// ✅ Automatically saved to cache!
};
return <button onClick={toggleTheme}>Current theme: {prefs.theme}</button>;
}
How It Works
1. First Time (No Cache)
const sCount = signify(0, { cache: { key: "counter" } });
// → Checks cache: nothing found
// → Uses initial value: 0
// → Saves 0 to cache
2. Value Changes
sCount.set(5);
// → Updates value to 5
// → Automatically saves 5 to cache
3. App Restart
const sCount = signify(0, { cache: { key: "counter" } });
// → Checks cache: finds 5
// → Uses cached value: 5 (ignores initial value 0)
Storage Types
You can choose where to store your cache:
localStorage (Default)
Data persists until manually cleared:
const sSettings = signify(defaultSettings, {
cache: {
key: "app-settings",
type: "LocalStorage", // Default, can omit this
},
});
sessionStorage
Data clears when browser tab closes:
const sTemporaryData = signify(initialData, {
cache: {
key: "temp-data",
type: "SessionStorage", // Change here
},
});
Real-World Examples
Example 1: User Preferences
const sUserSettings = signify(
{ theme: "light", language: "en" },
{ cache: { key: "user-settings" } }
);
function SettingsPage() {
const settings = sUserSettings.use();
return (
<div>
<select
value={settings.theme}
onChange={(e) =>
sUserSettings.set((prev) => {
prev.value.theme = e.target.value;
})
}
>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<select
value={settings.language}
onChange={(e) =>
sUserSettings.set((prev) => {
prev.value.language = e.target.value;
})
}
>
<option value="en">English</option>
<option value="es">Español</option>
</select>
</div>
);
}
Example 2: Shopping Cart
const sShoppingCart = signify([], {
cache: { key: "shopping-cart" },
});
const addToCart = (product) => {
sShoppingCart.set((prev) => {
const existing = prev.value.find((item) => item.id === product.id);
if (existing) {
existing.quantity += 1;
} else {
prev.value.push({ ...product, quantity: 1 });
}
});
// Automatically saved to cache!
};
function ShoppingCart() {
const cartItems = sShoppingCart.use();
return (
<div>
<h3>Cart ({cartItems.length} items)</h3>
{cartItems.map((item) => (
<div key={item.id}>
{item.name} x {item.quantity} - ${item.price}
</div>
))}
<button onClick={() => sShoppingCart.set([])}>Clear Cart</button>
</div>
);
}
Example 3: Form Draft Auto-Save
const sFormDraft = signify(
{ title: "", content: "" },
{ cache: { key: "article-draft" } }
);
function ArticleEditor() {
const draft = sFormDraft.use();
return (
<div>
<input
placeholder="Article title"
value={draft.title}
onChange={(e) =>
sFormDraft.set((prev) => {
prev.value.title = e.target.value;
})
}
/>
<textarea
placeholder="Write your article..."
value={draft.content}
onChange={(e) =>
sFormDraft.set((prev) => {
prev.value.content = e.target.value;
})
}
rows={10}
/>
<button onClick={() => sFormDraft.reset()}>Clear Draft</button>
{/* Draft automatically saves as you type! */}
</div>
);
}
Managing Cache
Clearing Cache Manually
// Clear specific cache
function clearUserSettings() {
localStorage.removeItem("user-settings");
sUserSettings.reset(); // Reset to initial values
}
// Clear all localStorage
function clearAllData() {
localStorage.clear();
// Reset all cached signifies
sUserSettings.reset();
sShoppingCart.reset();
sFormDraft.reset();
}
Checking What's Cached
// See what's stored
console.log(localStorage.getItem("user-settings"));
// Check storage size
function getStorageSize() {
let total = 0;
for (let key in localStorage) {
if (localStorage.hasOwnProperty(key)) {
total += localStorage[key].length;
}
}
return `${(total / 1024).toFixed(2)} KB`;
}
Best Practices
✅ Do's
// ✅ Use descriptive cache keys
const sUserData = signify(data, {
cache: { key: "user-profile-data" },
});
// ✅ Use different keys for different data
const sSettings = signify(settings, {
cache: { key: "app-settings" },
});
const sCart = signify([], {
cache: { key: "shopping-cart" },
});
// ✅ Consider using sessionStorage for temporary data
const sSearchResults = signify([], {
cache: {
key: "search-results",
type: "SessionStorage",
},
});
❌ Don'ts
// ❌ Don't cache sensitive data
const sPassword = signify("", {
cache: { key: "user-password" }, // Security risk!
});
// ❌ Don't use same key for different data
const sData1 = signify(data1, { cache: { key: "data" } });
const sData2 = signify(data2, { cache: { key: "data" } }); // Collision!
// ❌ Don't cache huge objects (localStorage has ~5MB limit)
const sHugeArray = signify(arrayWith1MillionItems, {
cache: { key: "huge-data" }, // Might exceed storage quota
});
Important Notes
Server-Side Rendering (SSR)
Cache doesn't work with SSR and will throw an error:
// ❌ This will throw error in SSR environments
const sData = signify(data, {
cache: { key: "my-data" },
});
If you're using SSR, don't use cache or conditionally enable it:
// ✅ Safe for SSR
const sData = signify(data, {
cache: typeof window !== "undefined" ? { key: "my-data" } : undefined,
});
Browser Storage Limits
- localStorage: ~5-10MB per domain
- sessionStorage: Same as localStorage but clears on tab close
- Data is stored as JSON strings
- Old browsers might not support these features
Data Format
All cached data is automatically converted to/from JSON:
// Your object
const data = { name: "John", age: 25 };
// Stored in cache as
// '{"name":"John","age":25}'
// Automatically parsed back to object when loaded
Troubleshooting
Cache Not Working?
- Check browser support: Make sure localStorage/sessionStorage is available
- Check storage quota: Browser might be out of space
- Check key conflicts: Make sure cache keys are unique
- Check SSR: Cache doesn't work server-side
Clear Cache During Development
// Clear during development
if (process.env.NODE_ENV === "development") {
localStorage.clear();
}
Summary
React Signify's cache feature is simple but powerful:
- Enable: Add
cache: { key: 'unique-name' }
to signify config - Automatic: Values save and load automatically
- Persistent: Data survives page refreshes and app restarts
- Flexible: Choose localStorage or sessionStorage
- Safe: Gracefully handles errors and SSR
Perfect for:
- ✅ User preferences and settings
- ✅ Shopping carts and form drafts
- ✅ App state that should persist
- ✅ Any data users don't want to lose
Start simple, add cache to your most important signifies, and enjoy the improved user experience!