Skip to content

watch

useBloc connects a bloc to a React component. But state often needs to reach code that has no component to render: a logger, an analytics pipeline, a localStorage sync, a <canvas> driven by an imperative library, or a test assertion. watch is the escape hatch for those cases — it observes one or more blocs outside of React and runs a callback whenever their state changes.

Observe one or more blocs outside React and run a callback on every state change.

// Single bloc
function watch<T extends StateContainerConstructor>(
bloc: T | BlocRef<T>,
callback: (bloc: InstanceType<T>) => void | typeof watch.STOP,
): () => void;
// Multiple blocs
function watch<T extends readonly BlocInput[]>(
blocs: T,
callback: (blocs: ExtractInstances<T>) => void | typeof watch.STOP,
): () => void;
ParameterTypeRequiredDescription
bloc / blocsT | BlocRef<T> or readonly BlocInput[]yesA bloc class (resolves to the default instance), an instance(Class, id) reference, or a readonly array of either.
callback(bloc: InstanceType<T>) => void | typeof watch.STOPyesRuns once immediately with the current instance(s), then on every subsequent state change. Return watch.STOP to tear down the subscription from inside the callback.

Returns: a stop() function. Calling it unsubscribes and is idempotent — calling it more than once is safe.

Behavior. watch resolves each input from the registry via ensure — creating the instance if it does not exist yet. It does not hold a ref: watch will not keep an otherwise-unused bloc alive, and a bloc it created can be disposed if nothing else references it. Subscriptions are coalesced per microtask flush — several synchronous mutations produce a single callback run — so callbacks land asynchronously after emit(). The callback fires once immediately on setup with the current state, then again after every subsequent change.

import {
const watch: WatchFn
watch
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class UserCubit
UserCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
name: string
name
: string }> {
constructor() {
super({
name: string
name
: 'Alice' });
}
}
const
const stop: () => void
stop
=
watch<typeof UserCubit>(bloc: typeof UserCubit | BlocRef<typeof UserCubit>, callback: (bloc: UserCubit) => void | unique symbol): () => void (+1 overload)
watch
(
class UserCubit
UserCubit
, (
user: UserCubit
user
) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('User state changed:',
user: UserCubit
user
.
StructuralContainer<{ name: string; }>.state: {
name: string;
}
state
.
name: string
name
);
});
// later — e.g. in a cleanup or on teardown of your module:
const stop: () => void
stop
();

Create a reference to a specific keyed bloc instance for use with watch.

function instance<T extends StateContainerConstructor>(
BlocClass: T,
args?: ExtractArgs<T>,
): BlocRef<T>;
ParameterTypeRequiredDescription
BlocClassT extends StateContainerConstructoryesThe bloc class to reference.
argsExtractArgs<T>noThe args identifying the instance — the same args you pass to useBloc. Resolved to a key via static key/structural hash.

Returns: a BlocRef<T> — a lightweight reference object that tells watch which keyed instance to resolve.

Behavior. By default watch(SomeCubit, ...) resolves the default instance. Wrap with instance(Class, args) to target the instance keyed by those args.

import {
const watch: WatchFn
watch
,
function instance<T extends StateContainerConstructor>(BlocClass: T, args?: ExtractArgs<T>): BlocRef<T>

Create a reference to a specific bloc instance, identified by its args. The key is derived the same way useBloc/acquire derive it.

@example

watch(instance(UserBloc, { userId: 'user-123' }), (userBloc) => {
console.log(userBloc.state.name);
});

instance
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class UserCubit
UserCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
name: string
name
: string }, {
userId: string
userId
: string }> {
static
UserCubit.key: (a: {
userId: string;
}) => string
key
= (
a: {
userId: string;
}
a
: {
userId: string
userId
: string }) =>
a: {
userId: string;
}
a
.
userId: string
userId
;
constructor() {
super({
name: string
name
: '' });
}
}
const
const stop: () => void
stop
=
watch<typeof UserCubit>(bloc: typeof UserCubit | BlocRef<typeof UserCubit>, callback: (bloc: UserCubit) => void | unique symbol): () => void (+1 overload)
watch
(
instance<typeof UserCubit>(BlocClass: typeof UserCubit, args?: {
userId: string;
} | undefined): BlocRef<typeof UserCubit>

Create a reference to a specific bloc instance, identified by its args. The key is derived the same way useBloc/acquire derive it.

@example

watch(instance(UserBloc, { userId: 'user-123' }), (userBloc) => {
console.log(userBloc.state.name);
});

instance
(
class UserCubit
UserCubit
, {
userId: string
userId
: 'user-123' }), (
user: UserCubit
user
) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(
user: UserCubit
user
.
StructuralContainer<{ name: string; }>.state: {
name: string;
}
state
.
name: string
name
);
});

A watch lives until you stop it. There are two ways, and forgetting both is the most common watch bug.

import {
const watch: WatchFn
watch
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class UserCubit
UserCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
name: string
name
: string }> {
constructor() {
super({
name: string
name
: '' });
}
}
const
const stop: () => void
stop
=
watch<typeof UserCubit>(bloc: typeof UserCubit | BlocRef<typeof UserCubit>, callback: (bloc: UserCubit) => void | unique symbol): () => void (+1 overload)
watch
(
class UserCubit
UserCubit
, (
user: UserCubit
user
) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(
user: UserCubit
user
.
StructuralContainer<{ name: string; }>.state: {
name: string;
}
state
.
name: string
name
);
});
// later — e.g. in a cleanup, useEffect teardown, or on teardown of your module:
const stop: () => void
stop
();

For one-shot or self-terminating watches, return the watch.STOP sentinel and the subscription tears itself down:

import {
const watch: WatchFn
watch
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class UserCubit
UserCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
onboardingComplete: boolean
onboardingComplete
: boolean }> {
constructor() {
super({
onboardingComplete: boolean
onboardingComplete
: false });
}
}
declare function
function runOnce(): void
runOnce
(): void;
watch<typeof UserCubit>(bloc: typeof UserCubit | BlocRef<typeof UserCubit>, callback: (bloc: UserCubit) => void | unique symbol): () => void (+1 overload)
watch
(
class UserCubit
UserCubit
, (
user: UserCubit
user
) => {
if (
user: UserCubit
user
.
StructuralContainer<{ onboardingComplete: boolean; }>.state: {
onboardingComplete: boolean;
}
state
.
onboardingComplete: boolean
onboardingComplete
) {
function runOnce(): void
runOnce
();
return
const watch: WatchFn
watch
.
WatchSingleFn.STOP: unique symbol
STOP
; // stop after the condition is met
}
});

Pass a readonly array to observe several blocs at once — the callback fires when any of them changes.

import {
const watch: WatchFn
watch
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class UserCubit
UserCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
name: string
name
: string }> {
constructor() {
super({
name: string
name
: '' });
}
}
class
class SettingsCubit
SettingsCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
theme: string
theme
: string }> {
constructor() {
super({
theme: string
theme
: 'light' });
}
}
declare function
function syncToServer(name: string, theme: string): void
syncToServer
(
name: string
name
: string,
theme: string
theme
: string): void;
// Watch several blocs at once; the callback fires when any of them changes.
const
const stop: () => void
stop
=
watch<readonly [typeof UserCubit, typeof SettingsCubit]>(blocs: readonly [typeof UserCubit, typeof SettingsCubit], callback: (blocs: readonly [UserCubit, SettingsCubit]) => void | unique symbol): () => void (+1 overload)
watch
([
class UserCubit
UserCubit
,
class SettingsCubit
SettingsCubit
] as
type const = readonly [typeof UserCubit, typeof SettingsCubit]
const
, ([
user: UserCubit
user
,
settings: SettingsCubit
settings
]) => {
function syncToServer(name: string, theme: string): void
syncToServer
(
user: UserCubit
user
.
StructuralContainer<{ name: string; }>.state: {
name: string;
}
state
.
name: string
name
,
settings: SettingsCubit
settings
.
StructuralContainer<{ theme: string; }>.state: {
theme: string;
}
state
.
theme: string
theme
);
});
ScenarioUse
A React component needs stateuseBloc
Non-React side effects (logging, analytics, syncing)watch
Bridging a bloc to imperative / non-React UIwatch
Test assertions on state over timewatch
You need selective, path-scoped observationcontainer.channel.subscribe(interest, cb)
import {
const watch: WatchFn
watch
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
interface
interface CartItem
CartItem
{
CartItem.price: number
price
: number;
}
class
class CartCubit
CartCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
items: CartItem[]
items
:
interface CartItem
CartItem
[] }> {
constructor() {
super({
items: CartItem[]
items
: [] });
}
get
CartCubit.total: number
total
() {
return this.
StructuralContainer<{ items: CartItem[]; }>.state: {
items: CartItem[];
}
state
.
items: CartItem[]
items
.
Array<CartItem>.reduce<number>(callbackfn: (previousValue: number, currentValue: CartItem, currentIndex: number, array: CartItem[]) => number, initialValue: number): number (+2 overloads)

Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.

@paramcallbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.

@paraminitialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.

reduce
((
sum: number
sum
,
i: CartItem
i
) =>
sum: number
sum
+
i: CartItem
i
.
CartItem.price: number
price
, 0);
}
}
declare const
const logger: {
info(msg: string, data: unknown): void;
}
logger
: {
function info(msg: string, data: unknown): void
info
(
msg: string
msg
: string,
data: unknown
data
: unknown): void };
const
const stop: () => void
stop
=
watch<typeof CartCubit>(bloc: typeof CartCubit | BlocRef<typeof CartCubit>, callback: (bloc: CartCubit) => void | unique symbol): () => void (+1 overload)
watch
(
class CartCubit
CartCubit
, (
cart: CartCubit
cart
) => {
const logger: {
info(msg: string, data: unknown): void;
}
logger
.
function info(msg: string, data: unknown): void
info
('cart changed', {
itemCount: number
itemCount
:
cart: CartCubit
cart
.
StructuralContainer<{ items: CartItem[]; }>.state: {
items: CartItem[];
}
state
.
items: CartItem[]
items
.
Array<CartItem>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
,
total: number
total
:
cart: CartCubit
cart
.
CartCubit.total: number
total
, // getters work here too
});
});

Drive an imperative library (a chart, a map, a canvas) from bloc state without a React wrapper:

import {
const watch: WatchFn
watch
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class MetricsCubit
MetricsCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
series: number[]
series
: number[] }> {
constructor() {
super({
series: number[]
series
: [] });
}
}
declare function
function createChart(el: HTMLElement): {
setData(series: number[]): void;
destroy(): void;
}
createChart
(
el: HTMLElement
el
:
interface HTMLElement

The HTMLElement interface represents any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it.

MDN Reference

HTMLElement
): {
function setData(series: number[]): void
setData
(
series: number[]
series
: number[]): void;
function destroy(): void
destroy
(): void;
};
function
function attachChart(el: HTMLElement): () => void
attachChart
(
el: HTMLElement
el
:
interface HTMLElement

The HTMLElement interface represents any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it.

MDN Reference

HTMLElement
) {
const
const chart: {
setData(series: number[]): void;
destroy(): void;
}
chart
=
function createChart(el: HTMLElement): {
setData(series: number[]): void;
destroy(): void;
}
createChart
(
el: HTMLElement
el
);
const
const stop: () => void
stop
=
watch<typeof MetricsCubit>(bloc: typeof MetricsCubit | BlocRef<typeof MetricsCubit>, callback: (bloc: MetricsCubit) => void | unique symbol): () => void (+1 overload)
watch
(
class MetricsCubit
MetricsCubit
, (
metrics: MetricsCubit
metrics
) => {
const chart: {
setData(series: number[]): void;
destroy(): void;
}
chart
.
function setData(series: number[]): void
setData
(
metrics: MetricsCubit
metrics
.
StructuralContainer<{ series: number[]; }>.state: {
series: number[];
}
state
.
series: number[]
series
);
});
// hand the caller a teardown that stops the watch and the chart
return () => {
const stop: () => void
stop
();
const chart: {
setData(series: number[]): void;
destroy(): void;
}
chart
.
function destroy(): void
destroy
();
};
}

Both observe a single container outside React; both fire once per microtask flush. The differences:

  • watch gives you the instance (so getters and methods are available), accepts multiple blocs, supports instance() references and the watch.STOP sentinel, and fires once immediately on setup.
  • channel.subscribe is the lower-level path-scoped surface on a container’s channel. You pass an interest thunk (the paths you care about, or ALL_PATHS for everything) and a callback that fires when a matching path changes. It does not fire on setup and gives you the changed path set rather than the instance — read state off the container yourself. Prefer watch for whole-state observation; reach for channel.subscribe when you need path-scoped interest.
import {
const watch: WatchFn
watch
,
function ensure<T extends StateContainerConstructor>(BlocClass: T, opts?: {
args?: ExtractArgs<T>;
}): InstanceType<T>

Ensure an instance exists without taking ownership (no ref added). Instance identity is derived purely from args, matching acquire.

ensure
,
const ALL_PATHS: typeof ALL_PATHS
ALL_PATHS
} from '@blac/core';
import {
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
} from '@blac/core';
class
class UserCubit
UserCubit
extends
class Cubit<S extends object = any, Args = void, Deps extends object = Record<string, never>>

Cubit<S> is a StateContainer<S> with emit / patch exposed as public mutation surface. Today it adds nothing structurally beyond StateContainer — both are inherited from the underlying StructuralContainer<S>. Kept as a real class (not a type alias) because downstream code does instance instanceof Cubit checks (see A2 audit).

The class body is intentionally empty: a no-op emit override would still go through applyState, and patch is inherited from StructuralContainer (path-diffed, microtask-flushed). If a caller needs the old "skip if no real change" patch semantics, they can wrap patch themselves or call emit after a manual equality check.

Cubit
<{
name: string
name
: string }> {
constructor() {
super({
name: string
name
: '' });
}
}
const
const user: UserCubit
user
=
ensure<typeof UserCubit>(BlocClass: typeof UserCubit, opts?: {
args?: void | undefined;
} | undefined): UserCubit

Ensure an instance exists without taking ownership (no ref added). Instance identity is derived purely from args, matching acquire.

ensure
(
class UserCubit
UserCubit
);
// channel.subscribe: path-scoped, fires on change (not on setup)
const
const unsub: () => void
unsub
=
const user: UserCubit
user
.
StructuralContainer<{ name: string; }>.channel: DirtyChannel<PathSet>
channel
.
DirtyChannel<PathSet>.subscribe(interest: () => PathSet, cb: (dirty: PathSet) => void): () => void
subscribe
(
() =>
const ALL_PATHS: typeof ALL_PATHS
ALL_PATHS
,
() => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(
const user: UserCubit
user
.
StructuralContainer<{ name: string; }>.state: {
name: string;
}
state
.
name: string
name
);
},
);
// watch: the instance, fires immediately, supports STOP and multiple blocs
const
const stop: () => void
stop
=
watch<typeof UserCubit>(bloc: typeof UserCubit | BlocRef<typeof UserCubit>, callback: (bloc: UserCubit) => void | unique symbol): () => void (+1 overload)
watch
(
class UserCubit
UserCubit
, (
u: UserCubit
u
) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(
u: UserCubit
u
.
StructuralContainer<{ name: string; }>.state: {
name: string;
}
state
.
name: string
name
);
});
  • System Events — the microtask flush and coalescing model behind watch
  • Tracking — why watch does not auto-track, and how useBloc does
  • Dependency Tracking — the React side of selective re-renders