Skip to content
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

Utilities to Implement #15

Open
13 of 18 tasks
NullVoxPopuli opened this issue Apr 2, 2024 · 3 comments
Open
13 of 18 tasks

Utilities to Implement #15

NullVoxPopuli opened this issue Apr 2, 2024 · 3 comments

Comments

@NullVoxPopuli
Copy link
Collaborator

NullVoxPopuli commented Apr 2, 2024

  • Object
  • Array
  • WeakMap
  • WeakSet
  • Map
  • Set
  • ArrayMap (Array.prototype.map, optimized)
  • SignalAsyncData / load (wrap a promise)
  • asyncFunction (wrap and invoke a function)
  • @signal (wrapper around new Signal.State)
  • localCopy / @localCopy
  • keepLatest / @keepLatest
  • dedupe / @dedupe
  • @cached (computed, but on a getter)
  • localStorage / @localStorage
    • other storages as well?
  • fetch
  • Relays - https://www.pzuraq.com/blog/on-signal-relays

Blocked on framework-specific semantics and timing (cleanup)

  • throttle
  • debounce
  • Image
  • effect
    • leaky microtaskqueue effect
  • waitUntil
  • resource
@justinfagnani
Copy link
Contributor

It would be nice to have a utility similar to MobX's reaction() function.

reaction() is very useful when you need to track the pervious value of a signal. You give it a tracked data function and an untracked effect function that's run when the value changes.

Something a bit like this:

export const reaction = <T>(
  data: () => T,
  effect: (value: T, previousValue: T) => void,
  equality = Object.is,
) => {
  const computed = new Signal.Computed(data);
  let previousValue = computed.get();
  let isReacting = false;
  const watcher = new Signal.subtle.Watcher(async () => {
    if (isReacting === true) {
      return;
    }
    isReacting = true;
    await 0;
    isReacting = false;
    const value = computed.get();
    if (!equality(previousValue, value)) {
      effect(value, previousValue);
      previousValue = value;
    }
  });
  watcher.watch(computed);
};

@NullVoxPopuli
Copy link
Collaborator Author

oo nice! that does seem useful -- I know quite a few folks that would like such a utility for caching or memoizing complex calculations (tho I don't know an exact use case, but I know it's desired!).

Would you be willing to submit a PR adding this utility along with a bunch of tests?
(so we can ensure behavior is retained as the polyfill (and spec) evolves?)

@JosXa
Copy link

JosXa commented Apr 29, 2024

Reminds me of Vue's watch function that allows to declare multiple signals ("refs") to track:
https://vuejs.org/api/reactivity-core.html#watch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants