diff --git a/frontend/src/components/render-page/hooks/use-on-height-change.ts b/frontend/src/components/render-page/hooks/use-on-height-change.ts new file mode 100644 index 000000000..f1b9b9d6f --- /dev/null +++ b/frontend/src/components/render-page/hooks/use-on-height-change.ts @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import useResizeObserver from '@react-hook/resize-observer' +import type { RefObject } from 'react' +import { useEffect, useState } from 'react' + +/** + * Monitors the height of the referenced {@link HTMLElement} and executes the callback on change. + * + * @param elementRef The reference that contains the element to watch + * @param onHeightChange The callback that should be executed if the height changes + */ +export const useOnHeightChange = ( + elementRef: RefObject, + onHeightChange: undefined | ((value: number) => void) +): void => { + const [rendererSize, setRendererSize] = useState(0) + useResizeObserver(elementRef, (entry) => { + setRendererSize(entry.contentRect.height) + }) + useEffect(() => { + const value = elementRef.current?.clientHeight + if (value === undefined) { + return + } + setRendererSize(value) + }, [elementRef]) + useEffect(() => { + onHeightChange?.(rendererSize + 1) + }, [rendererSize, onHeightChange]) +} diff --git a/frontend/src/components/render-page/renderers/document/document-markdown-renderer.tsx b/frontend/src/components/render-page/renderers/document/document-markdown-renderer.tsx index f2104d305..b8e1b6f90 100644 --- a/frontend/src/components/render-page/renderers/document/document-markdown-renderer.tsx +++ b/frontend/src/components/render-page/renderers/document/document-markdown-renderer.tsx @@ -11,12 +11,13 @@ import { useCalculateLineMarkerPosition } from '../../../markdown-renderer/hooks import { useMarkdownExtensions } from '../../../markdown-renderer/hooks/use-markdown-extensions' import { MarkdownToReact } from '../../../markdown-renderer/markdown-to-react/markdown-to-react' import { useDocumentSyncScrolling } from '../../hooks/sync-scroll/use-document-sync-scrolling' +import { useOnHeightChange } from '../../hooks/use-on-height-change' import { RendererType } from '../../window-post-message-communicator/rendering-message' import type { CommonMarkdownRendererProps, HeightChangeRendererProps } from '../common-markdown-renderer-props' import { DocumentTocSidebar } from './document-toc-sidebar' import styles from './markdown-document.module.scss' import useResizeObserver from '@react-hook/resize-observer' -import React, { useEffect, useMemo, useRef, useState } from 'react' +import React, { useMemo, useRef, useState } from 'react' export type DocumentMarkdownRendererProps = CommonMarkdownRendererProps & ScrollProps & HeightChangeRendererProps @@ -41,11 +42,7 @@ export const DocumentMarkdownRenderer: React.FC = newLinesAreBreaks }) => { const rendererRef = useRef(null) - const [rendererSize, setRendererSize] = useState() - useResizeObserver(rendererRef.current, (entry) => { - setRendererSize(entry.contentRect) - }) - useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange]) + useOnHeightChange(rendererRef, onHeightChange) const internalDocumentRenderPaneRef = useRef(null) const [internalDocumentRenderPaneSize, setInternalDocumentRenderPaneSize] = useState() @@ -74,7 +71,7 @@ export const DocumentMarkdownRenderer: React.FC = return (
= ({ newLinesAreBreaks }) => { const rendererRef = useRef(null) - const [rendererSize, setRendererSize] = useState() - useResizeObserver(rendererRef.current, (entry) => { - setRendererSize(entry.contentRect) - }) - useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange]) + useOnHeightChange(rendererRef, onHeightChange) const extensions = useMarkdownExtensions(baseUrl, RendererType.SIMPLE, []) return (