-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[@xstate/store] Improve atom architecture #5250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: d8374d6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Hey, this is beautiful. Just wanted to give you a more official measuring stick for reactive competence than just the diamond problem. Measuring StickMany regard this repo as the gold standard for testing reactivity: https://github.com/milomg/js-reactivity-benchmark There's a fork of it that Alien Signals uses here: https://github.com/transitive-bullshit/js-reactivity-benchmark I just cloned XState and plugged this branch (at the last passing commit) into the original js-reactivity-benchmark. I see several "Assertion failed" logs in all the benchmarks, including import { ReactiveFramework } from '../util/reactiveFramework'
import { createAtom } from '../../xstate/packages/xstate-store/src/atom'
export const xStateStoreFramework: ReactiveFramework = {
name: 'XState Store',
signal: initialValue => {
const s = createAtom(initialValue)
return {
write: v => s.set(v),
read: () => s.get(),
}
},
computed: fn => {
const c = createAtom(fn)
return {
read: () => c.get(),
}
},
effect: fn => createAtom(fn),
withBatch: fn => fn(),
withBuild: fn => fn(),
} Do You Need This?No. This is technically for signals libs. While atomic libs typically have all the functionality of signals, they don't have to be valid signals implementations. In fact, Recoil and Nanostores are incapable of running these benchmarks. Jotai's latest version also can't run them, though earlier versions could get through all but the But since your API is compatible, I would at least develop the initial implementation with this as an extra test suite. Making sure Zedux passes all these benchmarks has given us a lot of confidence that it's actually working and can handle all situations well. Unless I implemented it wrong, the fact that the |
Thanks @bowheart! I'll take a look at these benchmarks and see how many of these we can get to pass. |
…ai/xstate into davidkpiano/atom-diamond
packages/xstate-store/src/types.ts
Outdated
@@ -385,7 +394,9 @@ export type AnyAtom = Atom<any>; | |||
* atom.set(43); | |||
* ``` | |||
*/ | |||
export interface ReadonlyAtom<T> extends Readable<T> {} | |||
export interface ReadonlyAtom<T> extends BaseAtom<T>, Dependency, Subscriber { | |||
update(): boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should update
be on the atom? I thought it would be exclusive to computeds
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is exclusive to computeds (ReadonlyAtom
is the computed atom)
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
packages/xstate-store/src/alien.ts
Outdated
export interface Dependency { | ||
/** @internal */ | ||
_subs: Link | undefined; | ||
/** @internal */ | ||
_subsTail: Link | undefined; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see those types being directly exposed outside of this package but be careful when marking everything as @internal
on a type. That will become an empty interface in the emitted declaration and you don't want that.
export interface Atom<T> extends Subscribable<T>, Readable<T> { | ||
export interface BaseAtom<T> extends Subscribable<T>, Readable<T> {} | ||
|
||
export interface InternalBaseAtom<T> extends Subscribable<T>, Readable<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those Internal*
types are leaking as part of the public exports of the package right now because we just blindly reexport everything contained in this file. Ideally this would get fixed
Improved atom architecture with better dependency management (the diamond problem is solved!)
Optimized recomputation logic to prevent unnecessary updates
Added support for custom equality functions through
compare
option increateAtom
, allowing fine-grained control over when atoms update: