pmndrs / suspend-react

🚥 Async/await for React components
MIT License
1.38k stars 25 forks source link

How to clean ressources ? #20

Open ScreamZ opened 1 year ago

ScreamZ commented 1 year ago

Any way to clean resources using this library. I would like to open a socket using suspense but when the Host change, i need to reload a new socket and would like to clean effect the previous.

vezaynk commented 1 year ago

I too am wondering about this. I asked on Stackoverflow.

abernier commented 1 year ago

you have clear, eg: https://github.com/pmndrs/drei/blob/4aa04c93e4e86711f0a5a6777482a92d52988253/src/core/FaceControls.tsx#L350

vezaynk commented 1 year ago

@abernier so is the answer "use an effect"?

abernier commented 1 year ago

that's how I did yes -- that way if a dep changes (same as your suspend, in my case videoTextureSrc), it will be cleaned up and cleared

vezaynk commented 1 year ago

@abernier That's not ideal because it de-couples the effect from it's clean-up.

Suspend-react is aware of when the dependencies change, and so is best-positioned to run clean-up effects at the right time.

abernier commented 1 year ago

I thought like you primarily, I even asked about that on Discord

From @drcmda's answer, I guess this decoupling is intentional:

suspense is a cache, unmount means nothing to a cached entry, it will continue to be available

which makes sense to me, it's a cache, nothing more

If you want more, like a side-effect when your cache-key changes, then you have useEffect

vezaynk commented 1 year ago

I see.

Sounds like we should be wrapping suspend in our own hook.

Something like this.

const useSuspense(cb, deps) {
  const { value, cleanup } = suspend(cb)

  useEffect(() => {
    () => cleanup()
  }, deps)

 return value;
}

...but then we get the pitfall from a lack of reference-counting if two components use the same suspended keys.

useEffect(() => {
    () => {
      if (lastRef) evictFromCache();
      cleanup()
   }
  }, deps)

Makes me think suspend-react should be providing this.

nassosyian commented 3 months ago

I found an implementation of a "useMemoCleanup" hook from here that performs cleanup.

i've been using it in my own project like so:

const texture = useMemoCleanup( () => 
        [
            suspend(async () => {
                            // your code here
                            return texture;
                        }, []), 

            // cleanup func
            () => {
                texture.dispose();
            }
        ], [] );

and it seems to be working so far (even though i haven't heavily tested it)

hope this helps someone

vezaynk commented 3 months ago

@nassosyian How does this work? Wouldn't the memorized value be lost when suspense throws to the boundary?