#Why are nested effects not allowed?

1 messages · Page 1 of 1 (latest)

dull crane
#

I'm getting RuntimeError: NG0602: effect() cannot be called from within a reactive context. I was not able to find any explanation why effects should not be nested. Can you point me to the discussion?

Coming from solid.js, nesting effects is possible. Common use case is: outer effect creates and disposes of a heavy resource, inner effect updates that resource.

mortal glen
#

Do you have a more concrete example of the use case?
LinkedSignal (new signal derivated from another one) feels like a better fit.

dull crane
#

Here: ```
effect((onCleanup) => {
const texture = new Texture2D({ width: width(), height: height() });
onCleanup(() => texture.dispose())
effect(() => {
texture.update(data())
})
})

#

I was thinking, maybe I can computed((onCleanup) => new Texture2D()) but it doesn't give cleanup method

#

Maybe it's not obvious what I'm trying to do. When width and height change, I want to recreate the texture and set the new data. When data changes, I want to keep the previous texture.

woven ice
#

I would do something like:

function textureSignal(width, height, data) {
  const texture = linkedSignal({
    source: () => ({width: width(), height: height()}),
    computation: (source, {previous}) {
       previous?.value.destroy();
       const texture = new Texture2D(source);
       texture.update(untracked(data));
       return texture;
    }
  });
  inject(DestroyRef).onDestroy(() => texture().destroy());

  // the timing of this can be interesting - the texture is
  // created without the data when w/h change and must wait
  // for effect to sync it in
  effect(() => texture().update(data());
  return texture;
}
dull crane
#

Thanks! Is inject(DestroyRef).onDestroy(() => texture().destroy()); sort of a final cleanup?

The update I guess should happen immediately the first time, but I'll figure out the timing later.