-
Notifications
You must be signed in to change notification settings - Fork 3
Babel plugin
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.
It walks the file and looks for hook and context calls.
-
const [user, setUser] = useState(null)→ labeluser, plus the filename -
const AuthContext = createContext(null)→ labelAuthContext -
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.
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.
// @basis-ignoreat the top of a file skips transformation there (animation loops, wrappers, intentional sync).
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.
- 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.