@typesugar/react
v0.1.0
Published
π§ Compile-time React macros β Vue/Svelte-style reactivity with automatic dependency tracking
Downloads
60
Maintainers
Readme
@typesugar/react
Compile-time React macros β Vue/Svelte-style reactivity for React.
Overview
@typesugar/react brings modern reactivity patterns to React through compile-time macros. Write cleaner component code with automatic dependency tracking β no more manual dependency arrays.
Installation
npm install @typesugar/react
# or
pnpm add @typesugar/reactRequires React 18+ as a peer dependency.
Usage
state() β Reactive State
import { state } from "@typesugar/react";
function Counter() {
const count = state(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => count.set(c => c + 1)}>+</button>
</div>
);
}
// Compiles to:
// const [__count, __setCount] = useState(0);derived() β Computed Values
import { state, derived } from "@typesugar/react";
function Example() {
const count = state(0);
const doubled = derived(() => count * 2); // Auto-tracks dependencies!
return <p>Doubled: {doubled}</p>;
}
// Compiles to:
// const doubled = useMemo(() => __count * 2, [__count]);effect() β Side Effects
import { state, effect } from "@typesugar/react";
function DocumentTitle() {
const title = state("Hello");
effect(() => {
document.title = title; // Auto-extracts dependencies!
});
return <input value={title} onChange={e => title.set(e.target.value)} />;
}
// Compiles to:
// useEffect(() => { document.title = __title; }, [__title]);watch() β Explicit Dependencies
import { state, watch } from "@typesugar/react";
function UserProfile() {
const userId = state(1);
const profile = state(null);
watch([userId], async (id) => {
profile.set(await fetchProfile(id));
});
return profile ? <Profile data={profile} /> : <Loading />;
}component() β Embedded Components
import { component, each } from "@typesugar/react";
function TodoList() {
const todos = state([]);
// Embedded component β auto-hoisted and memoized
const TodoItem = component<{ todo: Todo }>(({ todo }) => (
<li>{todo.text}</li>
));
return (
<ul>
{each(todos, todo => <TodoItem todo={todo} />, t => t.id)}
</ul>
);
}match() β Pattern Matching
import { match } from "@typesugar/react";
type Status =
| { _tag: "loading" }
| { _tag: "error"; message: string }
| { _tag: "success"; data: Data };
function StatusView({ status }: { status: Status }) {
return match(status, {
loading: () => <Spinner />,
error: (e) => <Error message={e.message} />,
success: (s) => <DataView data={s.data} />,
});
}How It Works
The macros transform your code at compile time:
| You Write | It Becomes |
| ---------------------- | ------------------------------------ |
| state(0) | const [__val, __set] = useState(0) |
| derived(() => x * 2) | useMemo(() => x * 2, [x]) |
| effect(() => ...) | useEffect(() => ..., [autoDeps]) |
Automatic Dependency Extraction
The transformer analyzes your code to extract dependencies:
const a = state(1);
const b = state(2);
const sum = derived(() => a + b);
// Extracted deps: [a, b]Compile-Time Checks
- Purity verification β
derived()must be a pure function - Rules of hooks β Violations detected at compile time
- Exhaustive matching β
match()ensures all cases handled
Modes
React Mode (default)
Compiles to standard React hooks.
Fine-Grained Mode
Compiles to Solid.js-style signals for true fine-grained reactivity without VDOM diffing.
// Configure in transformer options
{
plugins: [typesugarPlugin({ reactMode: "fine-grained" })];
}API Reference
State Management
state<T>(initialValue)β Create reactive statederived<T>(computation)β Create computed valueeffect(effectFn)β Run side effect with auto-depswatch(deps, effectFn)β Run effect with explicit deps
Components
component<Props>(renderFn)β Define embedded componenteach(items, renderFn, keyFn)β Keyed iterationmatch(value, cases)β Pattern matching
Types
State<T>β Reactive state typeDerived<T>β Computed value typeEmbeddedComponent<P>β Component type
License
MIT
