store icon indicating copy to clipboard operation
store copied to clipboard

Derived Stores

Open crutchcorn opened this issue 1 year ago • 8 comments

This PR implements an initial Derived class implementation:

const count = new Store(10);

const doubleCount = new Derived([count], () => {
  return count.state * 2;
})

doubleCount.subscribe(() => console.log(doubleCount.state));
count.setState(() => 20);

This Derived implementation even solves the diamond problem:

"a" is the root node with "b" and "c" relying on it. Then "d" relies on both "b" and "c"

Where writes to "a" will call "d" twice (with a flicker of incorrect data known as a "Glitch") because of the dual-derived nature. Our implementation does not have this problem and therefore can be considered "glitch-free"

This is a push-based/hot signals implementation

Benchmarks

Due to the relatively naive nature of this code (I wrote it in one night at ~midnight) there are performance implication in using this. Namely, in our benchmarks we are a far cry from Angular or Solid's implementation, but come close to Vue's implementation:

crutchcorn avatar Feb 07 '24 09:02 crutchcorn

image

I've increased our performance and reduced our bundle size. We're no-longer the slowest on our own benchmark and are even 1.5x faster than Vue:

image

crutchcorn avatar Feb 09 '24 02:02 crutchcorn

Woo! 🏎️

tannerlinsley avatar Feb 09 '24 07:02 tannerlinsley

Angular is the fastest, nice 😄!

eneajaho avatar Feb 16 '24 11:02 eneajaho

View your CI Pipeline Execution ↗ for commit 6099591e52db0cee439c45ab0c8a1e4d38a3bbe3.

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 22s View ↗
nx run-many --target=build --exclude=examples/** ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2024-12-26 22:20:01 UTC

nx-cloud[bot] avatar Feb 17 '24 03:02 nx-cloud[bot]

Out of curiosity, what's the state of this PR and what's stopping it from being reviewed/merged?

lucasmotta avatar Jul 15 '24 13:07 lucasmotta

Out of curiosity, what's the state of this PR and what's stopping it from being reviewed/merged?

+1

AndrejNemec avatar Aug 07 '24 12:08 AndrejNemec

@tanstack/angular-store

npm i https://pkg.pr.new/@tanstack/angular-store@40
@tanstack/solid-store

npm i https://pkg.pr.new/@tanstack/solid-store@40
@tanstack/store

npm i https://pkg.pr.new/@tanstack/store@40
@tanstack/react-store

npm i https://pkg.pr.new/@tanstack/react-store@40
@tanstack/vue-store

npm i https://pkg.pr.new/@tanstack/vue-store@40
@tanstack/svelte-store

npm i https://pkg.pr.new/@tanstack/svelte-store@40

commit: 6099591

pkg-pr-new[bot] avatar Aug 12 '24 20:08 pkg-pr-new[bot]

I would prefer it I think

Tanner Linsley TanStack LLC On Aug 17, 2024 at 9:28 AM -0600, Kevin Van Cott @.***>, wrote:

@KevinVandy commented on this pull request. In packages/store/src/derived.ts:

+}

+export type Deps = Array<Derived | Store> + +export class Derived<TState> {

  • _store!: Store<TState>
  • rootStores = new Set<Store>()
  • deps: Deps
  • // Functions representing the subscriptions. Call a function to cleanup
  • _subscriptions: Array<() => void> = []
  • // What store called the current update, if any
  • _whatStoreIsCurrentlyInUse: Store | null = null
  • constructor(deps: Deps, fn: () => TState, options?: DerivedOptions<TState>) { would it be better if this had a flat options style like useQuery now does? new Derived({ storeKey: [], storeFn: () => alert("expensive") ...options }) — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

tannerlinsley avatar Aug 17 '24 17:08 tannerlinsley

I was originally holding off as performance didn't seem up-to-snuff, but comparing it against the TS39 Polyfill, it seems that we're roughly double the speed of that, so I want to merge this in so we can start using ASAP

Source of the benchmarks:

https://github.com/crutchcorn/js-reactivity-benchmark/tree/tanstack

crutchcorn avatar Nov 25 '24 09:11 crutchcorn