aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-09-21 13:50:18 +0200
committerArmand Philippot <git@armandphilippot.com>2022-09-21 13:50:18 +0200
commita5e6692f6dcab2157dc92b509f61418c06b2ebd7 (patch)
treeb5cebad901d8bc2f24c66b82ce7257c7da0539f1 /src/utils/hooks
parent08c7b3d0eb2ced622cdd3c4d14a3958ac8161cb8 (diff)
fix(projects): load content dynamically and refresh table of contents
The previous way of handling content import was causing issue. So I use dynamic import instead. However, the table of contents was not displayed because the wrapper is first empty. I added a mutation observer to refresh the table of contents when the body is updated.
Diffstat (limited to 'src/utils/hooks')
-rw-r--r--src/utils/hooks/use-headings-tree.tsx13
-rw-r--r--src/utils/hooks/use-mutation-observer.tsx28
2 files changed, 40 insertions, 1 deletions
diff --git a/src/utils/hooks/use-headings-tree.tsx b/src/utils/hooks/use-headings-tree.tsx
index 4646b4a..f7ab452 100644
--- a/src/utils/hooks/use-headings-tree.tsx
+++ b/src/utils/hooks/use-headings-tree.tsx
@@ -1,5 +1,6 @@
import { slugify } from '@utils/helpers/strings';
import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useMutationObserver } from './use-mutation-observer';
export type Heading = {
/**
@@ -32,13 +33,23 @@ const useHeadingsTree = (wrapper: HTMLElement): Heading[] => {
useState<NodeListOf<HTMLHeadingElement>>();
const [headingsTree, setHeadingsTree] = useState<Heading[]>([]);
- useEffect(() => {
+ const getHeadingsInWrapper = useCallback(() => {
const query = depths.join(', ');
const result: NodeListOf<HTMLHeadingElement> =
wrapper.querySelectorAll(query);
setAllHeadings(result);
}, [depths, wrapper]);
+ useEffect(() => {
+ getHeadingsInWrapper();
+ }, [getHeadingsInWrapper]);
+
+ useMutationObserver({
+ callback: getHeadingsInWrapper,
+ options: { childList: true },
+ nodeOrSelector: wrapper,
+ });
+
const getDepth = useCallback(
/**
* Retrieve the heading element depth.
diff --git a/src/utils/hooks/use-mutation-observer.tsx b/src/utils/hooks/use-mutation-observer.tsx
new file mode 100644
index 0000000..c56f7aa
--- /dev/null
+++ b/src/utils/hooks/use-mutation-observer.tsx
@@ -0,0 +1,28 @@
+import { useEffect } from 'react';
+
+type UseMutationObserverProps = {
+ callback: () => void;
+ options: MutationObserverInit;
+ nodeOrSelector: string | HTMLElement;
+};
+
+export const useMutationObserver = ({
+ callback,
+ options,
+ nodeOrSelector,
+}: UseMutationObserverProps) => {
+ useEffect(() => {
+ const targetNode =
+ typeof nodeOrSelector === 'string'
+ ? document.querySelector(nodeOrSelector)!
+ : nodeOrSelector;
+
+ const observer = new MutationObserver(callback);
+
+ observer.observe(targetNode, options);
+
+ return () => {
+ observer.disconnect();
+ };
+ }, [nodeOrSelector, options, callback]);
+};