Skip to content
Ilha
Esc
↑↓navigate↵open⌘Jpreview
On this page

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> ); };

Was this page helpful?