02 @dirtytalk/structural
Structural
Paths light up. Only their readers wake.
Chapter 02 Watch structural run, interactively →@dirtytalk/structural tracks changes in objects and arrays. A region is a set of interned path IDs, and each consumer subscribes to the paths it actually read.
pnpm add @dirtytalk/structural @dirtytalk/engine
Container
Extend StructuralContainer and mutate through the protected patch, emit or update.
import { StructuralContainer, ALL_PATHS } from '@dirtytalk/structural';
import { MicrotaskScheduler } from '@dirtytalk/engine';
interface CounterState {
count: number;
label: string;
}
class Counter extends StructuralContainer<CounterState> {
constructor() {
super(
{ count: 0, label: 'counter' },
{ scheduler: new MicrotaskScheduler() },
);
}
increment() {
this.patch({ count: this.state.count + 1 });
}
}
const counter = new Counter();
const unsub = counter.channel.subscribe(
() => ALL_PATHS,
(dirty) => console.log(counter.state, dirty),
);
counter.increment();
patch(partial)marks the keys of the partial directly.emit(next)andupdate(fn)diff along the observed paths only.- Updates are immutable replacements. Mutating
statein place is not tracked.
React
import { useStructural } from '@dirtytalk/structural/react';
const counter = new Counter();
function Count() {
const [state, container] = useStructural(counter);
return <button onClick={() => container.increment()}>{state.count}</button>;
}
Only fields read during render are recorded, so a change to label won’t re-render Count.
Other exports
| Export | Purpose |
|---|---|
PathInterner | string to ID interning, shared per class |
PathSet, PathSetSpace | the region type and its Space |
trackRender, ProxyCache | the proxy recorder behind useStructural |
diffAlongSkeleton, pathsFromPatch, getAt | diff and path helpers |
Values read from a tracked proxy are proxies too. Use raw() before comparing by identity or storing them.