zfb
GitHub repository

Type to search...

to open search from anywhere

Overview

Start with the zfb JSX runtime, its package subpath, and the setup-once component model.

What zudo-react provides

zudo-react is the JSX runtime shipped inside @takazudo/zfb. It gives components a small, explicit model: a component function runs once for each rendered instance, signals carry changing values, and the renderer updates bound DOM without calling the component again.

The runtime is not a React or Preact compatibility layer. It has no hooks, context, portals, class components, or general tree reconciliation. JSX describes work for zudo-react; it does not make the runtime behave like React.

Configure JSX

Install a zfb package version that includes zudo-react. zfb build and zfb dev compile page, component, and island JSX with the automatic transform and the fixed import source @takazudo/zfb/zudo-react, even when the project has no tsconfig.json; they ignore jsx and jsxImportSource in the project's tsconfig.json. A per-file @jsxImportSource pragma can override the build transform for that file, but a React or Preact pragma does not add support for those renderers. Set the following options in tsconfig.json so zfb check, editors, and TypeScript checks of test files use the same runtime's JSX types. Configure test-runner transforms separately in the runner's config.

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@takazudo/zfb/zudo-react"
  }
}

The compiler resolves the production helpers from @takazudo/zfb/zudo-react/jsx-runtime. Development transforms use @takazudo/zfb/zudo-react/jsx-dev-runtime. Both are package subpaths; zudo-react is not a separate package.

The TypeScript step in a full zfb check requires a project tsconfig.json; zfb check --skip-tsc skips that step and still runs the other checks. See zfb check.

Import runtime values from the core entry:

import { computed, signal } from "@takazudo/zfb/zudo-react";

A component runs once

Make a signal during setup and pass the signal itself to JSX. The event changes its value; the text binding updates on the next scheduled flush.

import { signal } from "@takazudo/zfb/zudo-react";

function Counter() {
  const count = signal(0);

  return (
    <button on:click={() => { count.value += 1; }}>
      Clicked {count} times
    </button>
  );
}

The component function is called once when this instance is rendered. A later count change updates the text slot and does not call Counter again. Each mounted instance gets its own setup and scope.

Passing a signal creates a live binding. Reading its value while JSX is being created takes a snapshot:

<p>{count}</p>
<p>{count.value}</p>

In this example, the first child is reactive. The second child is the number read during setup and stays that number. This rule also applies when values are passed through component props.

Where to go next

The remaining pages cover JSX descriptions, reactive updates, scopes, server rendering, hydration, forms, and structural regions. For the zfb side of island scheduling and persistence, see the island guides.

See also

Revision History

CreatedUpdated