Memo
Memoized rendering component that caches children and only re-renders when watched dependencies change. Perfect for optimizing expensive computations.
API Reference
Syntax
<Memo watch={watchSource} deep={boolean?}>
  {(value) => ReactNode}
</Memo>Props
watch: Data source to watch (store, function, or any value)deep(optional): Enable deep equality checking for nested objectschildren: Render function that receives the watched value
Examples
Expensive Component Optimization
import { createStore, Memo } from "zenbox";
const dataStore = createStore({
  items: Array.from({ length: 1000 }, (_, i) => ({
    id: i,
    value: Math.random(),
    name: `Item ${i}`,
  })),
  threshold: 0.5,
});
function ExpensiveVisualization() {
  return (
    <div>
      <h2>Data Visualization</h2>
      <Memo
        watch={() => ({
          items: dataStore.value.items,
          threshold: dataStore.value.threshold,
        })}
      >
        {({ items, threshold }) => {
          console.log("Rendering expensive visualization..."); // Only logs when dependencies change
          // Expensive computation
          const processedItems = items
            .filter((item) => item.value > threshold)
            .map((item) => ({
              ...item,
              processed: Math.pow(item.value, 2) * Math.sin(item.id),
            }))
            .sort((a, b) => b.processed - a.processed);
          return (
            <div className="expensive-chart">
              <h3>Processed Items ({processedItems.length})</h3>
              {processedItems.slice(0, 20).map((item) => (
                <div key={item.id} className="chart-item">
                  {item.name}: {item.processed.toFixed(4)}
                </div>
              ))}
            </div>
          );
        }}
      </Memo>
    </div>
  );
}Multi-Store Memoization
const cartStore = createStore({
  items: [
    { id: 1, name: "Laptop", price: 999, quantity: 1, category: "Electronics" },
    { id: 2, name: "Mouse", price: 25, quantity: 2, category: "Electronics" },
  ],
});
const settingsStore = createStore({
  currency: "USD",
  taxRate: 0.08,
  discountPercent: 0.1,
});
function CartSummary() {
  return (
    <Memo
      watch={() => ({
        items: cartStore.value.items,
        settings: settingsStore.value,
      })}
    >
      {({ items, settings }) => {
        console.log("Rendering complex cart summary..."); // Only when dependencies change
        // Complex calculations
        const subtotal = items.reduce(
          (sum, item) => sum + item.price * item.quantity,
          0
        );
        const discount = subtotal * settings.discountPercent;
        const tax = (subtotal - discount) * settings.taxRate;
        const total = subtotal - discount + tax;
        return (
          <div className="cart-summary">
            <div className="cart-items">
              {items.map((item) => (
                <div key={item.id} className="cart-item">
                  <span>{item.name}</span>
                  <span>
                    {item.quantity} × {settings.currency} {item.price}
                  </span>
                </div>
              ))}
            </div>
            <div className="cart-totals">
              <div>
                Subtotal: {settings.currency} {subtotal.toFixed(2)}
              </div>
              <div>
                Discount: -{settings.currency} {discount.toFixed(2)}
              </div>
              <div>
                Tax: {settings.currency} {tax.toFixed(2)}
              </div>
              <div>
                <strong>
                  Total: {settings.currency} {total.toFixed(2)}
                </strong>
              </div>
            </div>
          </div>
        );
      }}
    </Memo>
  );
}Best Practices
✅ Use for expensive computations - Perfect for components with heavy calculations
// Good - expensive computation that benefits from memoization
<Memo watch={() => dataStore.value}>
  {(data) => {
    const expensiveResult = heavyComputation(data);
    return <ComplexChart data={expensiveResult} />;
  }}
</Memo>❌ Don't use for frequently changing data
// Bad - counter changes frequently, memoization is useless
<Memo watch={() => counterStore.value.count}>
  {(count) => <div>{count}</div>}
</Memo>✅ Be specific with dependencies - Only watch data that affects rendered output
// Good - specific dependencies
<Memo
  watch={() => ({ items: store.value.items, threshold: store.value.threshold })}
>
  {({ items, threshold }) => (
    <ProcessedList items={items} threshold={threshold} />
  )}
</Memo>When to Use Memo vs Other Options
| Use Case | Recommended Approach | Why | 
|---|---|---|
| Expensive calculations | <Memo> | Caching prevents repeated computations | 
| Simple store access | usePick or useStore | Less overhead for simple cases | 
| Side effects | useWatch or useWatchEffect | Memo is for rendering, not side effects | 
| Always changing data | Regular components | Memoization won't help if data changes frequently | 
Related
<Watch>- Render prop component without memoizationuseComputed- Computed reactive valuesuseStore- Direct store subscription