Skip to content

Babel plugin

Petar Liovic edited this page Sep 9, 2026 · 1 revision

Hooks like useState(0) have no name at runtime. Reports need a name and a file, so a Babel plugin attaches those at build time. You keep importing from react.

What the plugin does

It walks the file and looks for hook and context calls.

  • const [user, setUser] = useState(null) → label user, plus the filename
  • const AuthContext = createContext(null) → label AuthContext
  • useEffect(...)effect_L42 (line number; effects have no variable name)
  • useMemo / useCallback → marked as computed, not as primary state

Those strings are passed into the Basis wrappers as an extra argument. You do not write them by hand.

Sketch of the rewrite (not the exact emitted code):

const [user, setUser] = useState(null);
// becomes something like
const [user, setUser] = useState(null, "Component.tsx -> user");

The wrappers accept that optional label. Production shims ignore it so it is never handed to React as an init function or a default context value.

Setup

Vite + @vitejs/plugin-react is the supported path. The plugin is listed under Babel; the Vite helper wires the rest. See the README.

Next.js / SWC is not instrumented yet. Without the plugin, hooks still run; they just show up as anonymous in the HUD and logs.

Ignore a file

// @basis-ignore

at the top of a file skips transformation there (animation loops, wrappers, intentional sync).

Production

Name extraction is compile-time. In production the plugin is idle and the package exports no-op wrappers around real React hooks. No graph, no labels used.

Limits

  • Renames follow the binding in source (user, not what you later call it in JSX).
  • Effects are line-based; edit the file and the id moves.
  • Multiple instances of the same component get distinct runtime keys; the label can still look the same in the console.

Clone this wiki locally