-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
[editable] Fix Memory Leak when switching between focused editables #5542
[editable] Fix Memory Leak when switching between focused editables #5542
Conversation
…ntainers I've found a memory leak in Slate React where-in when you'd switch between two pages, each with their own editor instance, auto-focusing on these elements causes a memory leak, where there would be a lot of Detached HTML Element's just floating around. At first I thought it a bunch of different bugs with chromium, but noticed that when I force removed the input elements from the dom before the component would unmount, we would still see small leak referencing "latestElement" (while simultaniously, I would still the element & children references in the `IN_FOCUSE` WeakMap) Looking at editable's code, I realized that we're storing state in a weird way, directly mutating it using `useMemo`, and React isn't removing all references (probably because its still stored in the WeakMap. The simple fix for this is what I've commited; using `useLayoutEffect`, we forcably remove the `latestElement` and references to it.
🦋 Changeset detectedLatest commit: 40aa9d4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a simple fix with great results. I'll land and release within the next day or two.
if you have time, please add a changeset, otherwise I will. Thanks!
ty for the changeset! 🙏 |
This one has introduced some regressions for us. My colleague's thinking: "If state goes, so should the reference and the element will be garbage collected. State is updated in a weird way, mutating memo is certainly not something that should be done like this. Perhaps using memo in such a way is the thing that is introducing the memory leak, because it don't think it gets cleared deterministically, but remove shouldn't be called It feels like the issue is useMemo." |
@dylans this also breaks our implementation useEffect(() => {
editor.children = value
editor.onChange()
ReactEditor.focus(editor) // this line now causes the editor to blank out!! if removed, its working but editor doesnt get initial focus
}, [value, editor])
...
<Slate
editor={editor}
initialValue={[]}
> |
Crash for us too on unmount.
I recreated our setup: https://stackblitz.com/edit/react-egzyvh?file=src%2FApp.js |
Reverting per the above discussion. |
@dylans for what its worth: I tried |
Description
I've found a memory leak in
slate-react
where-in when you'd switch between two pages, each with their own editor instance, auto-focusing on these elements causes a memory leak, where there would be a lot of Detached HTML Element's just floating around.At first I thought it a bunch of different bugs with chromium, but noticed that when I force removed the input elements from the dom before the component would unmount, we would still see small leak referencing "latestElement" (while simultaneously, I would still the element & children references in the
IS_FOCUSED
WeakMap) Looking at editable's code, I realized that we're storing state in a weird way, directly mutating it usinguseMemo
, and React isn't removing all references (probably because its still stored in the WeakMap.).The simple fix for this is what I've commited; using
useLayoutEffect
, we forcably remove thelatestElement
and references to it, before react unmounts the component.Example
(Both of these examples were run using memlab, in an isolated test environment)
Before (Has Big Dom Leak)
https://github.com/ianstormtaylor/slate/assets/1474758/1ac76419-c48d-48ff-a759-994c268ea72f
After (No Memory Leak)
https://github.com/ianstormtaylor/slate/assets/1474758/e0a3961c-18cb-42d2-93a5-b01edbb3e52c
Context
We're using an older version of slate (0.91), but even when doing an upgrade in an isolated branch, we still see this issue. We're also using the most recent version of React (18.2.0).
Checks
yarn test
.yarn lint
. (Fix errors withyarn fix
.)yarn start
.)yarn changeset add
.)