StunkStunk
Core Concepts

Derive

Create reactive derived state from a single chunk using .derive().

.derive() is a method on every chunk that creates a new reactive, read-only chunk based on a transformation function. The derived chunk updates automatically whenever the source changes.

import { chunk } from "stunk";

const price = chunk(100);

const discounted = price.derive((p) => p * 0.9);
const formatted = price.derive((p) => `₦${p.toFixed(2)}`);

price.set(200);

discounted.get(); // 180
formatted.get(); // "₦200.00"

The derived chunk is read-only at the TypeScript type level — set() and reset() do not exist on ReadOnlyChunk<T>. Update the source chunk instead.


Chaining

Derived chunks can themselves be derived:

const count = chunk(10);
const doubled = count.derive((n) => n * 2);
const label = doubled.derive((n) => `Value: ${n}`);

count.set(5);
label.get(); // "Value: 10"

Cleanup

A derived chunk stays subscribed to its source as long as both exist. To stop a derived chunk from updating while keeping the source alive, call destroy() on the derived chunk:

const discounted = price.derive((p) => p * 0.9);

discounted.destroy(); // stops listening, source still works

In React, cleanup happens automatically when the component unmounts. Manual destroy() is only needed when using derived chunks outside of React.


In React

Define the derived chunk outside the component, then read with useChunkValue():

import { chunk } from "stunk";
import { useChunkValue } from "stunk/react";

const price = chunk(100);
const discounted = price.derive((p) => p * 0.9);

function DiscountedPrice() {
  const value = useChunkValue(discounted);

  return <p>Discounted: ${value}</p>;
}

.derive() vs select() vs computed()

.derive()select()computed()
SourceSingle chunkSingle chunkMultiple chunks
Shallow equalityNoYes (useShallowEqual)Yes (automatic)
ChainableYesYesVia derive()
Best forSimple transformsObject slicesMulti-chunk derivation

What's next?

On this page