StunkStunk
Getting Started

Quick Start

Go from zero to reactive state in under 5 minutes.

This guide walks you through the core Stunk workflow — creating state, reading it, updating it, and reacting to changes.

Make sure you've completed Installation before continuing.


Create a chunk

A chunk is the fundamental unit of state in Stunk. You create one by calling chunk() with an initial value.

import { chunk } from "stunk";

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

Chunks are defined outside components or functions — they are global reactive containers, not component-local state.

Read and update state

Every chunk has get(), peek(), set(), and reset() methods.

count.get(); // 0 — read and track as dependency
count.peek(); // 0 — read without tracking

count.set(10); // set directly
count.set((prev) => prev + 1); // update from previous value → 11
count.reset(); // back to initial value → 0

Use peek() when you need the current value but don't want it to trigger recomputes in computed() or derived state.

Subscribe to changes

Use subscribe() to react to state changes outside of a framework:

const unsubscribe = count.subscribe((value) => {
  console.log("count changed:", value);
});

count.set(5); // logs: "count changed: 5"
count.set(6); // logs: "count changed: 6"

// Clean up when done
unsubscribe();

Use in React

Import useChunk from stunk/react to bind a chunk to a React component:

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

const counter = chunk(0);

function Counter() {
  const [count, setCount] = useChunk(counter);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount((n) => n + 1)}>Increment</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}

The component re-renders only when counter changes — nothing else triggers a re-render.

Derive state

Derive a new reactive value from an existing chunk using .derive():

const price = chunk(100);

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

price.set(200);
discounted.get(); // 180

For deriving from multiple chunks, use computed(). In v3, dependencies are tracked automatically — just call .get() on any chunk inside the function:

import { chunk, computed } from "stunk";

const price = chunk(100);
const quantity = chunk(3);

const total = computed(() => price.get() * quantity.get());

total.get(); // 300

quantity.set(5);
total.get(); // 500 — automatically recomputed

No dependency arrays. computed() tracks any chunk whose .get() is called during execution. Use .peek() to read a value without registering it as a dependency.


Putting it all together

Here's a complete example combining chunks, computed state, and React hooks:

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

const price = chunk(50);
const quantity = chunk(2);

const total = computed(() => price.get() * quantity.get());

function Cart() {
  const [qty, setQty] = useChunk(quantity);
  const totalValue = useChunkValue(total);

  return (
    <div>
      <p>Price: ${price.get()}</p>
      <p>Quantity: {qty}</p>
      <p>Total: ${totalValue}</p>
      <button onClick={() => setQty((n) => n + 1)}>Add item</button>
      <button onClick={() => setQty((n) => Math.max(0, n - 1))}>
        Remove item
      </button>
    </div>
  );
}

What's next?

On this page