⚡️(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:
@@ -12,7 +12,7 @@ import { BlockNoteView } from '@blocknote/mantine';
|
|||||||
import '@blocknote/mantine/style.css';
|
import '@blocknote/mantine/style.css';
|
||||||
import { useCreateBlockNote } from '@blocknote/react';
|
import { useCreateBlockNote } from '@blocknote/react';
|
||||||
import { HocuspocusProvider } from '@hocuspocus/provider';
|
import { HocuspocusProvider } from '@hocuspocus/provider';
|
||||||
import { useEffect } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
|
|
||||||
@@ -79,6 +79,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
|
|||||||
const { setEditor } = useEditorStore();
|
const { setEditor } = useEditorStore();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isSynced: isConnectedToCollabServer } = useProviderStore();
|
const { isSynced: isConnectedToCollabServer } = useProviderStore();
|
||||||
|
const refEditorContainer = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useSaveDoc(doc.id, provider.document, isConnectedToCollabServer);
|
useSaveDoc(doc.id, provider.document, isConnectedToCollabServer);
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
@@ -154,7 +155,9 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useHeadings(editor);
|
useHeadings(editor);
|
||||||
useShortcuts(editor);
|
|
||||||
|
useShortcuts(editor, refEditorContainer.current);
|
||||||
|
|
||||||
useUploadStatus(editor);
|
useUploadStatus(editor);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -166,7 +169,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
|
|||||||
}, [setEditor, editor]);
|
}, [setEditor, editor]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box ref={refEditorContainer}>
|
||||||
{errorAttachment && (
|
{errorAttachment && (
|
||||||
<Box $margin={{ bottom: 'big', top: 'none', horizontal: 'large' }}>
|
<Box $margin={{ bottom: 'big', top: 'none', horizontal: 'large' }}>
|
||||||
<TextErrors
|
<TextErrors
|
||||||
@@ -186,7 +189,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
|
|||||||
<BlockNoteSuggestionMenu />
|
<BlockNoteSuggestionMenu />
|
||||||
<BlockNoteToolbar />
|
<BlockNoteToolbar />
|
||||||
</BlockNoteView>
|
</BlockNoteView>
|
||||||
</>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ export const useHeadings = (editor: DocsBlockNoteEditor) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setHeadings(editor);
|
setHeadings(editor);
|
||||||
|
|
||||||
editor?.onChange(() => {
|
const unsubscribe = editor?.onChange(() => {
|
||||||
setHeadings(editor);
|
setHeadings(editor);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
resetHeadings();
|
resetHeadings();
|
||||||
|
unsubscribe();
|
||||||
};
|
};
|
||||||
}, [editor, resetHeadings, setHeadings]);
|
}, [editor, resetHeadings, setHeadings]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import { useEffect } from 'react';
|
|||||||
|
|
||||||
import { DocsBlockNoteEditor } from '../types';
|
import { DocsBlockNoteEditor } from '../types';
|
||||||
|
|
||||||
export const useShortcuts = (editor: DocsBlockNoteEditor) => {
|
export const useShortcuts = (
|
||||||
|
editor: DocsBlockNoteEditor,
|
||||||
|
el: HTMLDivElement | null,
|
||||||
|
) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (event.key === '@' && editor?.isFocused()) {
|
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
|
if (!el) {
|
||||||
document.addEventListener('keydown', handleKeyDown);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
el.addEventListener('keydown', handleKeyDown);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', handleKeyDown);
|
el.removeEventListener('keydown', handleKeyDown);
|
||||||
};
|
};
|
||||||
}, [editor]);
|
}, [editor, el]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const useUploadStatus = (editor: DocsBlockNoteEditor) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
editor.onChange((_, context) => {
|
const unsubscribe = editor.onChange((_, context) => {
|
||||||
const blocksChanges = context.getChanges();
|
const blocksChanges = context.getChanges();
|
||||||
|
|
||||||
if (!blocksChanges.length) {
|
if (!blocksChanges.length) {
|
||||||
@@ -90,7 +90,12 @@ export const useUploadStatus = (editor: DocsBlockNoteEditor) => {
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
unsubscribe();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubscribe();
|
||||||
|
};
|
||||||
}, [editor, t]);
|
}, [editor, t]);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user