ILHA003: Atom handle used from a different island
You read or wrote an atom handle while a different component was rendering.
An atom handle belongs to the component that created it. Calling it while another root is active throws ILHA003, because the value lives in a different registry.
Why it happens
You stored a handle in a module variable, a global, or a closure and called it from another island.
Bad
import { atom } from "ilha";
let shared: (() => number) | undefined;
const Source = () => {
const count = atom(0);
shared = count;
return <p>{count}</p>;
};
const Reader = () => <p>{shared?.()}</p>;
Fixed
Share state with createContext() and context() inside one root, or pass the value as a prop:
import { const atom: AtomFnatom, const context: <A>(ctx: IlhaContext<A>) => AtomHandle<A>Read a context value as an atom handle. Subscribes the active fiber on read.context, const createContext: <A>(defaultValue: A) => IlhaContext<A>createContext } from "ilha";
const const Count: IlhaContext<number>Count = createContext<number>(defaultValue: number): IlhaContext<number>createContext(0);
const const Reader: () => ViewReader = () => {
const const count: AtomHandle<number>count = context<number>(ctx: IlhaContext<number>): AtomHandle<number>Read a context value as an atom handle. Subscribes the active fiber on read.context(const Count: IlhaContext<number>Count);
return <JSX.IntrinsicElements.p: HTMLAttributes<HTMLParagraphElement>p>{const count: AtomHandle<number>count}</JSX.IntrinsicElements.p: HTMLAttributes<HTMLParagraphElement>p>;
};
const const App: () => ViewApp = () => {
const const count: AtomHandle<number>count = atom<number>(init: number | Atom<number>, options?: AtomOptions<number> | undefined): AtomHandle<number> (+1 overload)An existing Effect atom, or a plain value. Store a function with
`atom.lazy(() => fn)`; the `ilha/oxlint` rule `function-in-atom` flags
`atom(fn)`.atom(0);
return (
<const Count: IlhaContext<number>Count.IlhaContext<number>.Provider: (props: ContextProviderProps<number>) => ViewProvider ContextProviderProps<number>.value: numbervalue={const count: AtomHandle
() => number
count()}>
<JSX.IntrinsicElements.button: ButtonHTMLAttributesbutton type?: string | undefinedtype="button" EventProps<HTMLButtonElement>.onclick?: ((event: Targeted<HTMLButtonElement, MouseEvent>) => void) | undefinedonclick={() => const count: AtomHandle<number>count.AtomHandle<number>.update: (f: (current: number) => number) => voidupdate((n: numbern) => n: numbern + 1)}>
Add
</JSX.IntrinsicElements.button: ButtonHTMLAttributesbutton>
<const Reader: () => ViewReader />
</const Count: IlhaContext<number>Count.IlhaContext<number>.Provider: (props: ContextProviderProps<number>) => ViewProvider>
);
};