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 gives you an extra option — shallow equality checking — which is useful when your selector returns objects and you want to avoid unnecessary updates.

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 }));
userName.get(); // "Fola" — didn't change, no update triggered

Shallow equality

By default, select() uses strict reference equality (!==) to detect changes — same as .derive(). This is fine for primitives, but for object selectors it means 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 object 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 unnecessary re-renders when selecting a slice of a large object chunk.


Read-only enforcement

select() is strictly read-only. Calling set() or reset() throws:

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

userName.set("Tunde"); // ❌ "Cannot set values directly on a selector"
userName.reset(); // ❌ "Cannot reset a selector chunk"

Update the source chunk instead:

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

Chaining

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

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

select() vs .derive()

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

Use .derive() for simple value transforms. Use select() when you're slicing an object chunk and want precise control over when updates propagate.


In React

Derive outside the component, then pass to useChunkValue() since selectors are read-only:

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); // read-only

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

useDerive exists in v2 but will be removed in v3. Derive or select outside the component and pass the result directly to useChunkValue() instead.


What's next?

On this page