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

update template to avoid potential memory leaks #154

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

achim-k
Copy link
Collaborator

@achim-k achim-k commented Sep 4, 2024

Changelog

None

Docs

None

Description

Updates the panel template with

  • a comment to discourage adding new dependencies to the main useLayoutEffect hook
  • cleanup function for the useLayoutEffet

jtbandes
jtbandes previously approved these changes Sep 4, 2024
Copy link
Member

@jtbandes jtbandes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems ok, but it's still a bit vague as to why this would lead to memory leaks. In some ways, it makes sense that onRender accesses the current state to perform some logic. Perhaps we need to find a better pattern for onRender if we are suggesting that onRender should not have a dependency on the state. cc @defunctzombie for ideas

@defunctzombie
Copy link
Contributor

// Adding other dependencies here is discouraged as it can lead to memory leaks. Consider using other effects for your panel logic.

As a reader this does not tell me how it can lead to memory leaks and what it means to use other effects for the panel logic.

What would happen if you didn't have that comment but added this cleanup logic?

I also don't understand why we need to this in the panel if the layoutEffect is about to assign a new value? If the panel is removed we should be clearing that at the ExtensionAdapter layer?

@@ -23,7 +23,7 @@ function ExamplePanel({ context }: { context: PanelExtensionContext }): JSX.Elem
// rendering before the next render call, studio shows a notification to the user that your panel is delayed.
//
// Set the done callback into a state variable to trigger a re-render.
setRenderDone(() => done);
setRenderDone(done);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need a closure here as the panel extension adapter creates a new function for every render. It turned out that removing this closure fixes the memory leak I was encountering.

Copy link
Member

@jtbandes jtbandes Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is wrong — I think you might be misreading the existing code. It is not () => done() but () => done. The reason is since useState supports a function argument (oldState) => newState, it assumes the given done function is supposed to be called and calls it immediately rather than updating the state variable. See docs: https://react.dev/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead (we should probably link to these docs)

@achim-k
Copy link
Collaborator Author

achim-k commented Sep 6, 2024

// Adding other dependencies here is discouraged as it can lead to memory leaks. Consider using other effects for your panel logic.

As a reader this does not tell me how it can lead to memory leaks and what it means to use other effects for the panel logic.

I have removed that comment again.

What would happen if you didn't have that comment but added this cleanup logic?

I also don't understand why we need to this in the panel if the layoutEffect is about to assign a new value? If the panel is removed we should be clearing that at the ExtensionAdapter layer?

It turned out that the cleanup logic is not helping with the memory leak. The main change that fixed it was to remove the closure from setRenderDone(() => done). It's still a bit unclear to me why this fixed it, but the memory retainer tree below indicated that it had to do something with the renderDone callback.

Screenshot from 2024-09-05 17-24-57

@achim-k achim-k changed the title add comment about hook dependencies and cleanup function update template to avoid potential memory leaks Sep 6, 2024
@jtbandes jtbandes dismissed their stale review September 6, 2024 23:46

significant changes

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

Successfully merging this pull request may close these issues.

3 participants