@blac/core has no dependency on React. You can use blocs in vanilla JavaScript, Node.js scripts, worker threads, or any framework — without @blac/react installed. This page covers the two main patterns: observing state with watch and owning the lifecycle with acquire/release.
watch is the primary way to react to state changes outside a component. It creates a subscription, fires the callback once immediately with the current state, and then on every subsequent change.
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<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.
@param ― start The index to the beginning of the specified portion of stringObj.
@param ― end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end.
If this value is not specified, the substring continues to the end of stringObj.
slice(0, 8) + '...');
} else {
var console:Console
console.
Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
watch returns a stop function. Always call it when the subscription is no longer needed. Forgetting is the most common outside-React leak — a subscription you never stop keeps the bloc alive and runs your callback for the life of the process. See watch for the full API.
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<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<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<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<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.
In React, useBloc owns the acquire/release pair for you. Outside React you call them directly. Every acquire increments the ref count; the matching release decrements it. At ref count zero the instance is disposed.
Acquire an instance with ref tracking (ownership semantics). Instance
identity is derived purely from args (via the class's static key(args),
a structural hash of args, or the default sentinel when there are none).
@param ― BlocClass - The StateContainer class constructor
@param ― opts.args - Construction/identity args; derives the instance key
@param ― opts.refId - Named reference ID for debugging; auto-generated if omitted
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<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.
Acquire an instance with ref tracking (ownership semantics). Instance
identity is derived purely from args (via the class's static key(args),
a structural hash of args, or the default sentinel when there are none).
@param ― BlocClass - The StateContainer class constructor
@param ― opts.args - Construction/identity args; derives the instance key
@param ― opts.refId - Named reference ID for debugging; auto-generated if omitted
acquire(
classTaskQueueCubit
TaskQueueCubit);
const queue:TaskQueueCubit
queue.
TaskQueueCubit.enqueue: ()=>void
enqueue();
var console:Console
console.
Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
If you only need to read the current state and do not need to keep the instance alive, use borrow (throws if absent) or borrowSafe (returns an error object). Neither takes a ref, so no release is needed:
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<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.
The console.warn() static method outputs a warning message to the console at the "warning" log level. The message is only displayed to the user if the console is configured to display warning output. In most cases, the log level is configured within the console UI. The message may receive special formatting, such as yellow colors and a warning icon.
watch calls ensure internally — it does not take a ref. If you need both a stable subscription and a ref (to keep the instance alive while nothing else holds it), acquire first, then watch:
Acquire an instance with ref tracking (ownership semantics). Instance
identity is derived purely from args (via the class's static key(args),
a structural hash of args, or the default sentinel when there are none).
@param ― BlocClass - The StateContainer class constructor
@param ― opts.args - Construction/identity args; derives the instance key
@param ― opts.refId - Named reference ID for debugging; auto-generated if omitted
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<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.
Acquire an instance with ref tracking (ownership semantics). Instance
identity is derived purely from args (via the class's static key(args),
a structural hash of args, or the default sentinel when there are none).
@param ― BlocClass - The StateContainer class constructor
@param ― opts.args - Construction/identity args; derives the instance key
@param ― opts.refId - Named reference ID for debugging; auto-generated if omitted
Blocs work in Node.js without any changes. The module-level registry is per-module-graph, so in a single Node process the same singleton rules apply as in a browser tab.
For worker threads (node:worker_threads), each worker has its own module graph and therefore its own registry. Blocs do not cross thread boundaries — pass data between threads via the standard postMessage / MessageChannel API.
For long-running servers that handle multiple requests in the same process, apply the per-request registry isolation pattern to prevent state bleed between concurrent users.
Acquire an instance with ref tracking (ownership semantics). Instance
identity is derived purely from args (via the class's static key(args),
a structural hash of args, or the default sentinel when there are none).
@param ― BlocClass - The StateContainer class constructor
@param ― opts.args - Construction/identity args; derives the instance key
@param ― opts.refId - Named reference ID for debugging; auto-generated if omitted
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<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.
Acquire an instance with ref tracking (ownership semantics). Instance
identity is derived purely from args (via the class's static key(args),
a structural hash of args, or the default sentinel when there are none).
@param ― BlocClass - The StateContainer class constructor
@param ― opts.args - Construction/identity args; derives the instance key
@param ― opts.refId - Named reference ID for debugging; auto-generated if omitted