Zedux v2 Roadmap
Zedux v2 is on the horizon! Here's what we're planning on adding, deprecating, and removing plus some stuff we're still figuring out.
Planned Deprecations
- [x]
AtomInstance#getState- replaced withGraphNode#get(whichAtomInstanceinherits). (Completed by #151) - [x]
AtomInstance#setState- replaced withAtomInstance#set(a thin wrapper aroundSignalInstance#set). (Completed by #212) - [x] ~
AtomInstance#setStateDeep- replaced withAtomInstance#mutate(a thin wrapper aroundSignalInstance#mutate).~ (UPDATE: Not deprecating. Store atoms can't use.mutate. Switch to signals-based atoms for that). This has problems withundefinedin TS (see #95). TheStoreclass will retain itssetStateDeepmethod ~but changed to make undefined values a no op~ (UPDATE: not changing this. Prefer the newmutateAPIs). BothAtomInstanceandSignalwill instead havemutatemethods that finally introduce immer-style proxies natively to Zedux and fix theundefinedproblem naturally since they won't deal with anyRecursivePartialtypes. - [x] The
getInstanceatom getter - replaced withgetNode. - [x] The
selectatom getter - replaced withget. (Completed by #169) - [x]
useAtomSelector- replaced withuseAtomValue. (Completed by #169) - [x]
injectAtomSelector- replaced withinjectAtomValueor thegetatom getter. (Completed by #169) - [x] ~
injectStore- replaced withinjectSignal(this deprecation will almost definitely not be part of v2 initial release, but a minor version after).~ UPDATE: Not deprecating. It is still supported in the new@zedux/storespackage. Though it is considered legacy and it's recommended to migrate to the new signals-based atoms andinjectSignal. - [x] ~The
Storeclass and all helpers associated with it -createStore,getMetaData,removeAllMeta,removeMeta, all store-specificzeduxTypes(see #115),actionFactory,createReducer, and all type helpers for stores, actions, reducers, and subscribers.~ UPDATE: Not deprecating. These are still supported in the new@zedux/storespackage. Though they are considered legacy and it's recommended to migrate to the new signals-based atoms. - [x] ~All
Atom*Typetype utils - replaced with*Of(e.g.AtomStateType<myAtom>->StateOf<myAtom>).~ UPDATE: Not deprecating. These are still supported in the new@zedux/storespackage. Though they are considered legacy and it's recommended to update to the new signals-based atoms and*Oftypes. - [x] The
actionproperty on evaluation reasons.
Planned Removals
- [x] The
Selectorsclass (see #114). - [x] The
Graphclass (see #114). - [x] The
EvaluationStackclass (see #114). - [x] The
AtomInstanceBaseclass (see #114). - [x] The
SelectorCacheclass (see #114) - replaced withSelectorInstance. - [x]
AtomInstance#addDependentandSelectors#addDependentare replaced withGraphNode#on(see #114). - [x] The
IdGeneratorclass - replaced with methods onEcosystem. (Completed by #201) - [x] The
ZeduxPluginclass and its actions - plugins are being completely reworked (see below). (Completed by #168) - [x]
internalStore- Zedux will no longer store ecosystems in its module-level state. This keeps it pure(r) and prevents GC surprises - if an ecosystem with no callbacks registered with the JS runtime goes completely out of scope, it and all its atoms should be able to be cleaned up. (Completed by #190) - [x] The
storeproperty returned fromgetInternals- no direct replacement. Ecosystems will no longer be stored internally in Zedux module-level state. The global ecosystem will be returned by a newgetGlobalEcosystemexport. (Completed by #190) - [x]
getEcosystem- removed with no replacement. For multi-window setups that leveragegetInternals/setInternals, share your ecosystem reference across windows yourself rather than usinggetEcosystem('my-id')after callingsetInternalsin the child window. This should be about the same amount of code with less magic. (Completed by #190) - [x] The
sourceTypeproperty on evaluation reasons. - [x]
Ecosystem#registerPlugin- replaced withEcosystem#on. (Completed by #168) - [x]
Ecosystem#unregisterPlugin- replaced with calling the cleanup function returned fromEcosystem#on. (Completed by #168) - [x]
injectInvalidate. This is already deprecated, replaced byinjectSelf().invalidate. V2 removes it. (Completed by #170) - [x]
manualHydrationatom config option - Zedux will instead ~auto-detect any usages of thehydrateoption ininjectSignal~ UPDATE: Zedux now detects any usages of the newinjectHydrationinjector. (Completed by #195) - [x] The
AtomSelectorOrConfigtype - replaced withSelectorTemplate. (Completed by #212) - [x] ~The
AtomTemplateBaseclass - renamed toNodeTemplate.._createInstancerenamed to.newand.getInstanceIdrenamed to.hash.~ UPDATE: Not renaming the class._createInstancewas renamed to_instantiateandgetInstanceIdwas renamed togetNodeId(Completed by #211) - [x] The
flagsatom and ecosystem config option - renamed totags. This will affect the options passed toEcosystem#dehydrate(and nowEcosystem#findAll) -excludeFlagsrenamed toexcludeTagsandincludeFlagsrenamed toincludeTags. (Completed by #188) - [x]
wipe(the top-level exported function) - removed with no replacement. There's no internal store to clear. (Completed by #190) - [x] The hierarchy config from stores (see #94)
- [x] ~The
synchronousoption ofinjectEffect.~ (UPDATE: leaving as it still has a use, e.g. kicking off a promise immediately and setting it as the atom's promise). All effects will now run as soon as the atom's state factory returns. This solves the problem thatsynchronouswas trying to solve - where manual subscriptions aren't registered before the atom can be used - and also solves the problems withsynchronousitself - where its atom getter calls register graph edges (UPDATE: not a problem now since effect callbacks areuntracked). (Completed by #170) - [x]
Ecosystem#_incrementRefCount,Ecosystem#_decrementRefCount,Ecosystem#_refCount, and thedestroyOnUnmountecosystem config option.EcosystemProviderwill destroy on unmount instead. And custom ecosystems should handle ecosystem destruction manually (or just not, that's fine for most apps). (Completed by #190) - [x]
Ecosystem#wipe. This is just being hidden. It's always been recommended to useEcosystem#resetorEcosystem#destroyinstead. Now we won't have to recommend it. (Completed by #190) - [x] NEW:
Ecosystem#destroy. Ecosystems are no longer "destroyed". With the internalStore gone, ecosystems don't need to be removed from it. They'll continue to work just fine after reset.Ecosystem#resetwill have new options to enable resetting all internal ecosystem state (Completed by #190) - [x]
Ecosystem#atomDefaults. This is unnecessary bloat. Users can create atom factories themselves for defining standardized atom types. That gives full flexibility, is already documented, and has no real disadvantages to this ecosystem config option. (Completed by #212)
Planned Features
- [x] The new Signal primitive (see #115)
- [x] New plugin system (see #119) (Completed by #168)
- [x] ~
api.setto set all properties of an AtomAPI at once.~ UPDATE: not doing, at least for v2 - [ ] Remove the string key requirement of
atom. Keys will be auto-generated if not provided (but it's strongly recommended to pass one or use a build tool plugin to generate them for you). UPDATE: Will do this later, not as part of initial v2 release. - [x] Events (see #115). In addition to the signal built-in events, atoms will have
.on('invalidate', cb). If we remove lifecycles from signals, atoms will also have.on('cycle', cb). Ecosystems will also have "plugin events" (see #119). (Completed by #147, #158, and #168) - [x] ~
optimizeoption forEcosystem#batchthat will disable evaluation reason tracking for all updates resulting from any calls in the.batchcallback.~ UPDATE: Probably not doing, at least not now. After tons of benchmarking and profiling, I've found the evaluation reason tracking has very little overhead. - [x] Automatic dependency tracking for
injectEffect,injectPromise, ~injectCallback~, andinjectMemo- omit the deps array and Zedux will make the callback a reactive context similar to signals libs. UPDATE: only doinginjectMemofor now (Completed by #171) - [x] Improved parameters to
Ecosystem#findAll. Besides those already in #114, ~a.findAll(callback)overload for full control. That overload will apply toEcosystem#dehydrateas well.~ UPDATE: We instead switched.findAllto return an array so manual filtering, etc is easier (Completed by #204). - [x] NEW:
injectutility for reading contextual values (provided by React context) in atoms. (Completed by #172)
Stuff We're Still Figuring Out
- [x] Will phase 2 of the graph perf improvements be part of Zedux v2 or pushed back to v3? UPDATE: I've micro optimized Zedux's existing scheduler algorithm a lot for v2. I'm still planning on doing phase 2, but definitely not for v2.
- [x] ~Is the lifecycle
statusproperty of graph nodes used enough to merit it getting astatusgetter on top of the obfuscated single-letterlifecycleStatus property added by #114? We've never used it TMK for any purpose, but it's featured prominently in the docs. Maybe it just shouldn't be?~ We will add astatusgetter because we're further obfuscatinglifecycleStatus by making its value a number. Thestatusgetter will translate the number to a user-friendly string. - [x] ~Should we cut a
v2of the docs and leave v1 alone? Or should we update the existing doc pages.~ We will leave the v1 docs alone and partition the docs site by version - [x] Can the new signal primitive be made so it can use the TC39 proposal internally when (if) it's finalized? Not worth worrying about now. Zedux needs more control over events and update tracing than the proposal is proposing. Our signals are too powerful. But even so, we might be able to utilize the signal primitive for something, but that's a long way off.
- [x] The new type (introduced in #114) for arguments passed to
ecosystem.dehydrateandecosystem.findAlldoesn't have a way to specify that only a certain type of node should be returned - atoms or selectors (or signals soon) or a custom node type. What would this argument look like? (Completed by #204) - [x] ~Instead of the new
ecosystem.liveatom getters, should we make the ecosystem's own atom getters reactive by default? We would then addgetOnceandgetNodeOncemethods which would have the current behavior ofgetandgetNoderespectively. This would get rid of the concept of atom getters and make the ecosystem all you need to know. It would also be able to have parity with signals -signal.getandsignal.getOnce. It would also replaceinjectAtomGetterswithinjectEcosystemfor better parity with Zedux's hooks.~ This is officially the plan 🎉 . (Completed by #169) - [ ] The timeline! When will Zedux v2 be available? UPDATE: No fixed date yet, but I'm aiming to be stable and battle-tested by March 20, 2025, though perhaps not fully documented yet.
The first release candidate has been published! https://github.com/Omnistac/zedux/releases/tag/v2.0.0-rc.0
Zedux v2 is now considered usable and stable, at least as far as all public, non-obfuscated APIs go. There may still be some "technically breaking" changes for internal APIs, but nothing normal users should need to know about.
There may be more features and bug fixes before v2.0.0 lands. That is the purpose of release candidates after all. And, of course, there's lots to document.
The v2 migration guide can be considered a quick start for Zedux v2 for now.
TL;DR: If you don't mind the currently-sparse documentation, feel free to use v2!
pnpm i @zedux/react@next
Hey! Whats the status on this? v2 RC-10 seems to be stable for several months now, any updates on the timeline?
Hey @samuelhnrq thanks for asking. The v2 RCs have indeed been stable for several months. We've been using it in prod since rc.9 I believe. The only thing preventing the full release is docs which I've been getting to here and there since April. Most of the API docs are done and PR'd.
I'm currently working on a big side project (with Zedux and TanStack Start btw) that's taking lots of my time, but I'm hoping to get back to the docs in maybe two weeks. If I can knock everything out, early November sounds about right for the official release. I don't feel I can commit to a specific date right now, but it might be even sooner if I free up 50 hours or so soon.
AI tooling really needs the new docs, but if you're not too dependent on that, I do recommend using v2 over v1 already. It's a big upgrade that is already very battle tested and the TypeScript, code comments, and PR'd docs should be enough to get by.