zedux icon indicating copy to clipboard operation
zedux copied to clipboard

Zedux v2 Roadmap

Open bowheart opened this issue 1 year ago • 3 comments

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 with GraphNode#get (which AtomInstance inherits). (Completed by #151)
  • [x] AtomInstance#setState - replaced with AtomInstance#set (a thin wrapper around SignalInstance#set). (Completed by #212)
  • [x] ~AtomInstance#setStateDeep - replaced with AtomInstance#mutate(a thin wrapper around SignalInstance#mutate).~ (UPDATE: Not deprecating. Store atoms can't use .mutate. Switch to signals-based atoms for that). This has problems with undefined in TS (see #95). The Store class will retain its setStateDeep method ~but changed to make undefined values a no op~ (UPDATE: not changing this. Prefer the new mutate APIs). Both AtomInstance and Signal will instead have mutate methods that finally introduce immer-style proxies natively to Zedux and fix the undefined problem naturally since they won't deal with any RecursivePartial types.
  • [x] The getInstance atom getter - replaced with getNode.
  • [x] The select atom getter - replaced with get. (Completed by #169)
  • [x] useAtomSelector - replaced with useAtomValue. (Completed by #169)
  • [x] injectAtomSelector - replaced with injectAtomValue or the get atom getter. (Completed by #169)
  • [x] ~injectStore - replaced with injectSignal (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/stores package. Though it is considered legacy and it's recommended to migrate to the new signals-based atoms and injectSignal.
  • [x] ~The Store class and all helpers associated with it - createStore, getMetaData, removeAllMeta, removeMeta, all store-specific zeduxTypes (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/stores package. Though they are considered legacy and it's recommended to migrate to the new signals-based atoms.
  • [x] ~All Atom*Type type utils - replaced with *Of (e.g. AtomStateType<myAtom> -> StateOf<myAtom>).~ UPDATE: Not deprecating. These are still supported in the new @zedux/stores package. Though they are considered legacy and it's recommended to update to the new signals-based atoms and *Of types.
  • [x] The action property on evaluation reasons.

Planned Removals

  • [x] The Selectors class (see #114).
  • [x] The Graph class (see #114).
  • [x] The EvaluationStack class (see #114).
  • [x] The AtomInstanceBase class (see #114).
  • [x] The SelectorCache class (see #114) - replaced with SelectorInstance.
  • [x] AtomInstance#addDependent and Selectors#addDependent are replaced with GraphNode#on (see #114).
  • [x] The IdGenerator class - replaced with methods on Ecosystem. (Completed by #201)
  • [x] The ZeduxPlugin class 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 store property returned from getInternals - no direct replacement. Ecosystems will no longer be stored internally in Zedux module-level state. The global ecosystem will be returned by a new getGlobalEcosystem export. (Completed by #190)
  • [x] getEcosystem - removed with no replacement. For multi-window setups that leverage getInternals/setInternals, share your ecosystem reference across windows yourself rather than using getEcosystem('my-id') after calling setInternals in the child window. This should be about the same amount of code with less magic. (Completed by #190)
  • [x] The sourceType property on evaluation reasons.
  • [x] Ecosystem#registerPlugin - replaced with Ecosystem#on. (Completed by #168)
  • [x] Ecosystem#unregisterPlugin - replaced with calling the cleanup function returned from Ecosystem#on. (Completed by #168)
  • [x] injectInvalidate. This is already deprecated, replaced by injectSelf().invalidate. V2 removes it. (Completed by #170)
  • [x] manualHydration atom config option - Zedux will instead ~auto-detect any usages of the hydrate option in injectSignal~ UPDATE: Zedux now detects any usages of the new injectHydration injector. (Completed by #195)
  • [x] The AtomSelectorOrConfig type - replaced with SelectorTemplate. (Completed by #212)
  • [x] ~The AtomTemplateBase class - renamed to NodeTemplate. ._createInstance renamed to .new and .getInstanceId renamed to .hash.~ UPDATE: Not renaming the class. _createInstance was renamed to _instantiate and getInstanceId was renamed to getNodeId (Completed by #211)
  • [x] The flags atom and ecosystem config option - renamed to tags. This will affect the options passed to Ecosystem#dehydrate (and now Ecosystem#findAll) - excludeFlags renamed to excludeTags and includeFlags renamed to includeTags. (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 synchronous option of injectEffect.~ (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 that synchronous was trying to solve - where manual subscriptions aren't registered before the atom can be used - and also solves the problems with synchronous itself - where its atom getter calls register graph edges (UPDATE: not a problem now since effect callbacks are untracked). (Completed by #170)
  • [x] Ecosystem#_incrementRefCount, Ecosystem#_decrementRefCount, Ecosystem#_refCount, and the destroyOnUnmount ecosystem config option. EcosystemProvider will 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 use Ecosystem#reset or Ecosystem#destroy instead. 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#reset will 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.set to 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] ~optimize option for Ecosystem#batch that will disable evaluation reason tracking for all updates resulting from any calls in the .batch callback.~ 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~, and injectMemo - omit the deps array and Zedux will make the callback a reactive context similar to signals libs. UPDATE: only doing injectMemo for 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 to Ecosystem#dehydrate as well.~ UPDATE: We instead switched .findAll to return an array so manual filtering, etc is easier (Completed by #204).
  • [x] NEW: inject utility 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 status property of graph nodes used enough to merit it getting a status getter on top of the obfuscated single-letter lifecycleStatus 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 a status getter because we're further obfuscating lifecycleStatus by making its value a number. The status getter will translate the number to a user-friendly string.
  • [x] ~Should we cut a v2 of 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.dehydrate and ecosystem.findAll doesn'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.live atom getters, should we make the ecosystem's own atom getters reactive by default? We would then add getOnce and getNodeOnce methods which would have the current behavior of get and getNode respectively. 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.get and signal.getOnce. It would also replace injectAtomGetters with injectEcosystem for 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.

bowheart avatar Sep 10 '24 02:09 bowheart

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

bowheart avatar Mar 14 '25 13:03 bowheart

Hey! Whats the status on this? v2 RC-10 seems to be stable for several months now, any updates on the timeline?

samuelhnrq avatar Oct 07 '25 13:10 samuelhnrq

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.

bowheart avatar Oct 07 '25 21:10 bowheart