️(frontend) improve unsubscribe logic when unmounting components

We can now unsubscribe on the editor events,
improving performance and preventing memory leaks.
This commit is contained in:
Anthony LC
2025-11-04 14:22:37 +01:00
parent ad16c0843c
commit c5d5d3dec4
4 changed files with 26 additions and 11 deletions

View File

@@ -12,7 +12,7 @@ import { BlockNoteView } from '@blocknote/mantine';
import '@blocknote/mantine/style.css';
import { useCreateBlockNote } from '@blocknote/react';
import { HocuspocusProvider } from '@hocuspocus/provider';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs';
@@ -79,6 +79,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
const { setEditor } = useEditorStore();
const { t } = useTranslation();
const { isSynced: isConnectedToCollabServer } = useProviderStore();
const refEditorContainer = useRef<HTMLDivElement>(null);
useSaveDoc(doc.id, provider.document, isConnectedToCollabServer);
const { i18n } = useTranslation();
@@ -154,7 +155,9 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
);
useHeadings(editor);
useShortcuts(editor);
useShortcuts(editor, refEditorContainer.current);
useUploadStatus(editor);
useEffect(() => {
@@ -166,7 +169,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
}, [setEditor, editor]);
return (
<>
<Box ref={refEditorContainer}>
{errorAttachment && (
<Box $margin={{ bottom: 'big', top: 'none', horizontal: 'large' }}>
<TextErrors
@@ -186,7 +189,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
<BlockNoteSuggestionMenu />
<BlockNoteToolbar />
</BlockNoteView>
</>
</Box>
);
};

View File

@@ -9,12 +9,13 @@ export const useHeadings = (editor: DocsBlockNoteEditor) => {
useEffect(() => {
setHeadings(editor);
editor?.onChange(() => {
const unsubscribe = editor?.onChange(() => {
setHeadings(editor);
});
return () => {
resetHeadings();
unsubscribe();
};
}, [editor, resetHeadings, setHeadings]);
};

View File

@@ -2,7 +2,10 @@ import { useEffect } from 'react';
import { DocsBlockNoteEditor } from '../types';
export const useShortcuts = (editor: DocsBlockNoteEditor) => {
export const useShortcuts = (
editor: DocsBlockNoteEditor,
el: HTMLDivElement | null,
) => {
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === '@' && editor?.isFocused()) {
@@ -29,11 +32,14 @@ export const useShortcuts = (editor: DocsBlockNoteEditor) => {
}
};
// Attach the event listener to the document instead of the window
document.addEventListener('keydown', handleKeyDown);
if (!el) {
return;
}
el.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
el.removeEventListener('keydown', handleKeyDown);
};
}, [editor]);
}, [editor, el]);
};

View File

@@ -40,7 +40,7 @@ export const useUploadStatus = (editor: DocsBlockNoteEditor) => {
const { t } = useTranslation();
useEffect(() => {
editor.onChange((_, context) => {
const unsubscribe = editor.onChange((_, context) => {
const blocksChanges = context.getChanges();
if (!blocksChanges.length) {
@@ -90,7 +90,12 @@ export const useUploadStatus = (editor: DocsBlockNoteEditor) => {
return () => {
clearTimeout(timeoutId);
unsubscribe();
};
});
return () => {
unsubscribe();
};
}, [editor, t]);
};