Solid 2 Pending State Issue
We are running into a Solid 2 beta issue involving isPending, latest, and a memoized optimistic store object.
https://stackblitz.com/edit/solidjs-templates-bgdbj55p?file=src%2FApp.tsx
Problematic Pattern
const user = createMemo(() => store.user);
isPending(() => latest(() => user().email));
Expected Behavior
If only store.user.name is optimistically changed, email should stay not pending.
This should behave the same as direct store access:
isPending(() => latest(() => store.user.email));
Actual Behavior
After modifying name and then calling refresh(store), email reports pending only through the memoized object path:
isPending(() => latest(() => user().email));
Direct store access does not show the false pending state:
isPending(() => latest(() => store.user.email));
Root Cause
createMemo(() => store.user) introduces an intermediate reactive source whose value is the whole user object.
During isPending(() => latest(...)), Solid collects pending sources from the read path. The memoized object source is collected in addition to the final email field.
When refresh(store) runs, the optimistic store's firewall/projection is pending. That intermediate object source sees the refresh pending state, so email incorrectly appears pending even though the email leaf was not updated.
App-Level Fix
Avoid memoizing store objects when precise field-level pending state is needed. Memoize/read the leaf property instead:
const name = createMemo(() => store.user.name);
const email = createMemo(() => store.user.email);
isPending(() => latest(name));
isPending(() => latest(email));
Or use direct store access:
isPending(() => latest(() => store.user.email));
Takeaway
Avoid memoizing store objects if you need precise field-level pending state. Memo or read the leaf property instead.
The likely framework-level bug is that isPending + latest should treat the intermediate memo object as transparent and only count the final leaf source.
Solid 2 Pending State Issue
We are running into a Solid 2 beta issue involving
isPending,latest, and a memoized optimistic store object.https://stackblitz.com/edit/solidjs-templates-bgdbj55p?file=src%2FApp.tsx
Problematic Pattern
Expected Behavior
If only
store.user.nameis optimistically changed,emailshould stay not pending.This should behave the same as direct store access:
Actual Behavior
After modifying
nameand then callingrefresh(store),emailreports pending only through the memoized object path:Direct store access does not show the false pending state:
Root Cause
createMemo(() => store.user)introduces an intermediate reactive source whose value is the wholeuserobject.During
isPending(() => latest(...)), Solid collects pending sources from the read path. The memoized object source is collected in addition to the finalemailfield.When
refresh(store)runs, the optimistic store's firewall/projection is pending. That intermediate object source sees the refresh pending state, soemailincorrectly appears pending even though theemailleaf was not updated.App-Level Fix
Avoid memoizing store objects when precise field-level pending state is needed. Memoize/read the leaf property instead:
Or use direct store access:
Takeaway
Avoid memoizing store objects if you need precise field-level pending state. Memo or read the leaf property instead.
The likely framework-level bug is that
isPending + latestshould treat the intermediate memo object as transparent and only count the final leaf source.