diff --git a/documentation/solid-2.0/04-stores.md b/documentation/solid-2.0/04-stores.md index 19b859ad98..09effefcec 100644 --- a/documentation/solid-2.0/04-stores.md +++ b/documentation/solid-2.0/04-stores.md @@ -167,6 +167,8 @@ setStore(s => { This pairs naturally with `createProjection`, where returning a value from the derive function uses reconciliation automatically (keyed by `options.key`, default `"id"`). +Don't keep mutating an object after handing it to a store. A later in-place change to that object isn't observed, and assigning or reconciling the same object again doesn't pick it up either, because the store sees the same reference. Pass a fresh object instead (a new response, or a copy such as `{ ...next }`). This mostly affects test fixtures and caches that reuse one response object. + ### Shallow stores (`shallow: true`) By default stores track at property level all the way down — that is the model, and it is the right choice for almost all state. `shallow: true` is a **specialized performance opt-in** for one identifiable workload shape, not a general recommendation: reach for it when profiling shows ingestion cost on data whose records change wholesale. diff --git a/documentation/solid-2.0/07-dom.md b/documentation/solid-2.0/07-dom.md index 34d471747f..836f198a7b 100644 --- a/documentation/solid-2.0/07-dom.md +++ b/documentation/solid-2.0/07-dom.md @@ -93,6 +93,8 @@ let el;
(el = node), autofocus]} />; // assigned ``` +A ref runs before the element is inserted into the page. At that point `el.isConnected` is `false`, and `el.ownerDocument` is the inert document of the template the element was cloned from, so `el.ownerDocument.defaultView` is `null`. Don't reach the window or document through the element inside a ref: use the global `window`/`document`, or do work that needs the attached element (measuring, reading computed styles) in `onSettled`. + #### Two-phase directive factories (owned setup, unowned application) The recommended directive pattern is **two-phase**, similar in spirit to “split effects” (compute phase vs apply phase): diff --git a/documentation/solid-2.0/MIGRATION.md b/documentation/solid-2.0/MIGRATION.md index af0b280069..9f214499eb 100644 --- a/documentation/solid-2.0/MIGRATION.md +++ b/documentation/solid-2.0/MIGRATION.md @@ -1009,6 +1009,8 @@ const value = createMemo(async function* () { }); ``` +Cleanup is not immediate. When the owner is disposed, or a re-run replaces the stream, Solid calls the generator's `return()`, but a generator waiting at an `await` can't finish until that `await` settles. The source stays subscribed until it produces another value or ends. If the memo only forwards values, return the iterable itself (`createMemo(() => observable$)`): Solid closes it right away. A source that isn't an async iterable (a callback subscription, an Observable) needs an adapter (see #4182, which also tracks prompt cleanup for generators). + **Solid → External (`observable`):** There's no drop-in replacement. `observable()` produced a standard Observable that external libraries could subscribe to. In 2.0, use `createEffect` to push signal changes to an external subscriber: ```js diff --git a/packages/solid/CHEATSHEET.md b/packages/solid/CHEATSHEET.md index f596d7f020..5bbfc7c0c8 100644 --- a/packages/solid/CHEATSHEET.md +++ b/packages/solid/CHEATSHEET.md @@ -33,6 +33,7 @@ import { createOptimisticStore, isPending, latest, + createDeferred, refresh, affects, untrack, @@ -225,6 +226,11 @@ const user = createMemo(() => fetchUser(id())); // Peek at the in-flight value during a transition latest(id); +// A memo that may lag but never leads (React's useDeferredValue): after its +// first answer, a refetch keeps the last value on screen instead of holding +// the change; isPending(() => rows()) reports the refetch. +const rows = createDeferred(() => fetchRows(period())); + // Force recompute of a derived read after a server write. // Action: call from handlers/effects/actions, not pure reads. // A bare refresh() re-asks the SAME question — it is quiet (isPending stays @@ -441,6 +447,8 @@ hydrate(() => , document.getElementById("root")!);