StunkStunk
Core Concepts

Select

Create a read-only derived chunk from a single source with optional shallow equality.

select() creates a read-only derived chunk from a source chunk using a selector function. It's similar to .derive() but adds one important option — shallow equality checking — which prevents unnecessary updates when your selector returns an object.

import { chunk, select } from "stunk";

const user = chunk({ name: "Fola", age: 25, role: "admin" });

const userName = select(user, (u) => u.name);

userName.get(); // "Fola"

user.set((prev) => ({ ...prev, age: 26 })); // age changed, name didn't
userName.get(); // "Fola" — no update triggered

Shallow equality

By default, select() uses strict reference equality (!==) to detect changes. This is fine for primitives, but for object selectors a new object reference always triggers an update even if the contents are identical.

Enable useShallowEqual to compare object contents instead:

const user = chunk({ name: "Fola", age: 25 });

// Without useShallowEqual — new reference = always updates
const info = select(user, (u) => ({ name: u.name, age: u.age }));

// With useShallowEqual — only updates when name or age actually changes
const info = select(user, (u) => ({ name: u.name, age: u.age }), {
  useShallowEqual: true,
});

This is especially useful in React — it prevents re-renders when selecting a slice of a large object chunk that hasn't meaningfully changed.


Read-only

select() returns a ReadOnlyChunk<T>set() and reset() are not present on the returned object. Update the source chunk instead:

const userName = select(user, (u) => u.name);

// @ts-expect-error — set does not exist on ReadOnlyChunk
userName.set("Tunde");

// Update source instead
user.set((prev) => ({ ...prev, name: "Tunde" }));
userName.get(); // "Tunde"

Chaining

Selectors can be chained — each returns a new ReadOnlyChunk that inherits the same options:

const user = chunk({ profile: { name: "Fola", age: 25 } });
const profile = select(user, (u) => u.profile);
const name = select(profile, (p) => p.name);

In React

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

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

const user = chunk({ name: "Fola", age: 25, role: "admin" });
const userName = select(user, (u) => u.name, { useShallowEqual: true });

function UserName() {
  const name = useChunkValue(userName);

  return <p>Hello, {name}</p>;
}

select() vs .derive()

.derive()select()
SyntaxMethod on chunkStandalone import from stunk
Read-onlyYesYes
Shallow equalityNoYes (useShallowEqual)
ChainableYesYes
Best forSimple transformsObject slices, perf-sensitive selectors

What's next?

On this page