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

feat: lazy observables #604

Closed
wants to merge 1 commit into from

Conversation

benjamind
Copy link

@benjamind benjamind commented Dec 19, 2022

Summary

Adds capability for 'lazy observables'. When a proxy is subscribed/unsubscribed, optional onBecomeObserved and onBecomeUnobserved callbacks can be fired. This allows users to lazily subscribe to async data to update state similar to mobx lazy observables.

Usage:

  let intervalId = -1;
  const state = proxy<any>(
    { count: 0, counting: false }, // proxy some state, as usual
    
    // when the proxy is subscribed:
    () => {
      // initialize the value on first subscription
      state.count = 10
      // and start an async interval to update it
      intervalId = setInterval(() => {
        state.count += 1
      }, 100)
    },
    () => {
      // clear async interval when no longer observed
      clearInterval(intervalId)
      intervalId = -1
    }
  )

The optional callbacks are fired when the proxy first becomes observed by a subscription and when all subscriptions are unsubscribed. Not as atomic as the mobx approach which can pass back the individual properties subscribed to within the state object, but this same behavior can be achieved by nesting proxies instead with valtio.

Check List

  • yarn run prettier for formatting code and docs

@vercel
Copy link

vercel bot commented Dec 19, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
valtio ✅ Ready (Inspect) Visit Preview Dec 19, 2022 at 9:34PM (UTC)

@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit cecede2:

Sandbox Source
React Configuration
React Typescript Configuration
React Browserify Configuration
React Snowpack Configuration
React Parcel Configuration

@dai-shi
Copy link
Member

dai-shi commented Dec 20, 2022

Thanks for the suggestion.

We don't extend our vanilla.ts code to add functionalities.
Instead, we make it extendable with buildProxyFunction.

Can you try what you can do on your end? It would be a good use case and worth documenting.

We could put listeners in arguments of buildProxyFunction if that helps.

diff --git a/src/vanilla.ts b/src/vanilla.ts
index d67c9e6..5534456 100644
--- a/src/vanilla.ts
+++ b/src/vanilla.ts
@@ -131,6 +131,8 @@ const buildProxyFunction = (
 
   versionHolder = [1] as [number],
 
+  listeners = new Set<Listener>(),
+
   proxyFunction = <T extends object>(initialObject: T): T => {
     if (!isObject(initialObject)) {
       throw new Error('object required')
@@ -140,7 +142,6 @@ const buildProxyFunction = (
       return found
     }
     let version = versionHolder[0]
-    const listeners = new Set<Listener>()
     const notifyUpdate = (op: Op, nextVersion = ++versionHolder[0]) => {
       if (version !== nextVersion) {
         version = nextVersion

@benjamind
Copy link
Author

Ah ok I can give that a go!

@dai-shi
Copy link
Member

dai-shi commented Dec 20, 2022

Please see #528 for some simple use cases as well as some discussions.

@dai-shi
Copy link
Member

dai-shi commented Apr 4, 2023

Closing as stale. Please open a new one if necessary.

@dai-shi dai-shi closed this Apr 4, 2023
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

Successfully merging this pull request may close these issues.

2 participants