re-reduced
A typed, functional state-machine + effect container for component-scoped logic. It owns your transitions and effect intent — and delegates server state to your data layer.
import { , , } from "@re-reduced/react";
const = ("counter", {
: { : 0 },
: () => ({
: (() => ({ : . + 1 })),
: <number>((, ) => ({ : . + })),
}),
: () => ({ : () => .. % 2 === 0 }),
});
// in a component — re-renders only when the slice it reads changes
function () {
const = ();
const = (, () => ..);
const = (, (, ) => ..);
return { , , : .. };
}import { , , } from "@re-reduced/react";
function () {
const = ();
const = (, () => ..);
const = (, (, ) => ..);
return (
<>
<>
{} { ? "(even)" : "(odd)"}
</>
< ="button" ={() => ..(1)}>
+1
</>
< ="button" ={..}>
reset
</>
</>
);
}import { , } from "@re-reduced/core";
const = ("users", {
: {
: [] as [],
: "idle" as "idle" | "loading" | "ready",
},
: () => ({
: (() => ({ ..., : "loading" as })),
: <[]>((, ) => ({
...,
,
: "ready" as ,
})),
}),
// side-effects are declared as intents, interpreted by the adapter
: () => [
.("load", (, { }) =>
<[]>({
: ["users"],
: () => .(),
: () => .(),
}),
),
],
});Signal-backed, fine-grained
State lives in per-field signals. A component re-renders only when the slice it reads actually changes — no selector discipline, no memo juggling.
Typed to the bone
Action payloads, derivations, and effect interpreters are fully inferred. Zero `any` in your app code, exhaustive intent coverage at compile time.
Effects as data
Side-effects are declared as intents and interpreted by the renderer adapter. The container stays pure, portable, and unit-testable.
Multi-renderer
The same container definition runs under React and Preact. Server state stays in your data layer — re-reduced composes, it doesn't replace.
v1 (the Redux/redux-saga helper) is frozen and still published as re-reduced@2. v2 ships under the @re-reduced/* scope.