Skip to content

[✨] Need destroy hook. #74

Closed
Closed
@mhevery

Description

@mhevery

Is your feature request related to a problem?

Today you can call cleanup to release resources specific to the VM. But what if the component needs to notify a parent component that it is being returned? In such a case there is no hook which can survive resuming.

Example:

export default component$(() => {
  const list = useStore([1,2,3];
  return (
    <Parent>
    {list.map((item)=> <Child/>}
    </Parent>
  );
})

const CHILDREN = createContextId<Array<Signal<any>>>('children');
export const Parent = compont$(( )=> {
  const context = useStore([]);
  useContextProvider(CHILDREN, context);
  return <Slot/>;
});

export const Child = compont$(( )=> {
  const ref = useSignal();
  const context = useContext(CHILDREN);
  useTask$(({cleanup}) => {
    context.push(ref);
    cleanup({
      // PROBLEM HERE ❌ ❌ ❌ ❌ 
      // The issue is that the cleanup gets called during serialization
      // on the server, which releases the children from the parents.
      // What we want instead is to call "cleanup" when the component 
      //  is destroyed
      context.splice(context.indexOf(ref), 1);
    });
  });
  return <div ref={ref}><Slot/></div>;
});

The issue is that the cleanup gets called during serialization on the server, which releases the children from the parents. What we want instead is to call "cleanup" when the component is destroyed.
that

Describe the solution you'd like

Proposed solution

export const Child = compont$(( )=> {
  const ref = useSignal();
  const context = useContext(CHILDREN);

  // OPTION ONE
  useDestroyTask$(() => {
      context.splice(context.indexOf(ref), 1);
  });

  // OPTION TWO
  useTask$(({destroy$}) => {
      destroy$(() => {
        context.splice(context.indexOf(ref), 1);
      });
  });

  return <div ref={ref}><Slot/></div>;
});

Describe alternatives you've considered

HACK

export const Child = compont$(( )=> {
  const ref = useSignal();
  const context = useContext(CHILDREN);
  useTask$(() => {
    context.push(ref);
  });
  useVisibleTask$(({cleanup}) => {
    // HACK ❌ ❌ ❌ ❌ ❌ 
    cleanup({
      context.splice(context.indexOf(ref), 1);
    });
    },
    { strategy: 'document-idle' }
  );
  return <div ref={ref}><Slot/></div>;
});

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions