mirror of
https://github.com/hanzoai/chat.git
synced 2026-09-30 20:51:17 +00:00
recoil 0.7.7 is recoil's LAST release and its final act is to break React 19.
`currentRendererSupportsUseSyncExternalStore()` destructures
`ReactCurrentDispatcher` out of
`React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED`, which React 19
renamed. The read returns undefined and throws before the first paint — the
green-build/blank-page that 7d4adc71af measured and reverted. There is no
version to bump to, so the library goes.
The client already had TWO state libraries. This leaves ONE.
249 files: 197 source + 52 test + the store itself
client/src is now recoil-free; `recoil` is out of client/package.json,
out of the lockfile, and out of node_modules (129 packages dropped).
Store rewritten on jotai (client/src/store):
atom({key, default}) -> atom(default)
selector / selectorFamily -> derived atom / atomFamily of one
atomFamily + reset -> `family()` = atomFamily of atomWithReset
useRecoilCallback -> useAtomCallback
RecoilRoot -> jotai Provider
SetterOrUpdater / RecoilState -> Setter<T> / WritableAtom (common/types)
Three semantic differences recoil hid, each fixed deliberately rather than
transcribed — a recoil `snapshot` is IMMUTABLE, so a read after a reset still
sees the pre-reset value, while jotai's `get` is live:
- useClearConvoState read the conversation AFTER resetting it, to decide
whether to also reset its latest message. Reordered to read first.
- useClearStates read conversationKeysAtom AFTER awaiting the clears that
reset it; live reads would have returned [] and skipped every per-key
reset. The keys are now read before the clears.
- useLatestMessage keyed a selectorFamily by an ARRAY of parent ids. recoil
hashes params by value; jotai's atomFamily compares by identity and would
have leaked one atom per render. Now a useMemo'd derived atom keyed by
content.
Pure-logging recoil `effects` are deleted, not ported — they only called
logger.log with a key re-parsed out of `node.key`. The one effect that did
real work (conversationByIndex: localStorage write-through + history
pushState) is a write-wrapper over the stored atom, and gets the index
directly instead of splitting it back out of a serialized node key.
Deletes two duplicate helper modules' worth of overlap: store/jotai-utils.ts
folds into store/utils.ts, so there is one home and one name for each atom
helper. ToggleSwitch stops shipping two implementations behind an
`isRecoilState()` sniff and is now one component.
Also drops the recoil pnpm patch that appeared in the tree alongside this
work: it exists to keep recoil alive under React 19, and pnpm fails a patch
entry for a package nothing depends on.
MEASURED: `npm run frontend` exit 0 (23.8s). React is still 18.3.1 here —
this commit changes state management ONLY, so it is separately revertable
from the React 19 bump that follows.
Co-authored-by: Hanzo Dev <[email protected]>
16 lines
437 B
TypeScript
16 lines
437 B
TypeScript
import { createStore } from 'jotai';
|
|
|
|
export type Store = ReturnType<typeof createStore>;
|
|
|
|
/**
|
|
* A fresh jotai store, optionally seeded — the equivalent of the
|
|
* `initializeState` prop tests used to hand to Recoil's root.
|
|
*
|
|
* render(<Provider store={seed((s) => s.set(myAtom, 1))}>{ui}</Provider>)
|
|
*/
|
|
export function seed(init?: (store: Store) => void): Store {
|
|
const store = createStore();
|
|
init?.(store);
|
|
return store;
|
|
}
|