createRoot, dispose and detached roots
createRoot(fn, options?) creates an ownership scope and calls fn(dispose) untracked.
createRoot(fn, options?) creates an ownership scope and calls fn(dispose) untracked. Everything created inside (effects, memos, cleanups, child roots) is disposed together when you call dispose(). createRoot returns what fn returns; if fn throws, the root is disposed and the error rethrown.
An attached root (the default) is also disposed when its parent owner is. { detached: true } removes that link: only dispose ends it. render() and renderHook() use roots; you need createRoot for state and effects that live outside any component (a store module with subscriptions, a test).