Skip to content

Commit

Permalink
perf(useMutationobserver): optimiza performance (#3049)
Browse files Browse the repository at this point in the history
* refactor(usemutationobserver): optimiza performance

* chore(usemutationobserver): fix spell

* Update src/hooks/useMutationObserver.ts
  • Loading branch information
HaixingOoO authored Sep 2, 2024
1 parent fca95e6 commit 6089140
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions src/hooks/useMutationObserver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useRef, useEffect } from 'react';
import debounce from 'lodash/debounce';
import isEqual from 'lodash/isEqual';
import useLatest from './useLatest';

const DEFAULT_OPTIONS = {
debounceTime: 0,
Expand All @@ -11,31 +13,46 @@ const DEFAULT_OPTIONS = {
} as MutationObserverInit,
};

type Options = typeof DEFAULT_OPTIONS;

export default function useMutationObservable(
targetEl: HTMLElement | null,
cb: MutationCallback,
options = DEFAULT_OPTIONS,
) {
const observeRef = useRef(null);
const optionsRef = useRef<Options>();
const signalRen = useRef(0);
const callbackRef = useLatest(cb);

useEffect(() => {
if (!cb || typeof cb !== 'function') return;
const { debounceTime } = options;
observeRef.current = new MutationObserver(debounceTime > 0 ? debounce(cb, debounceTime) : cb);
}, [cb, options]);
if (!isEqual(options, optionsRef.current)) {
signalRen.current += 1;
}

optionsRef.current = options;

useEffect(() => {
if (!targetEl || !targetEl?.nodeType) return;

const { config } = options;
try {
const { debounceTime, config } = optionsRef.current;
const mutationCallback: MutationCallback = (...args) => {
callbackRef.current(...args);
};
observeRef.current = new MutationObserver(
debounceTime > 0 ? debounce(mutationCallback, debounceTime) : mutationCallback,
);
observeRef.current.observe(targetEl, config);
} catch (e) {
console.error(e);
}

return () => {
observeRef.current.disconnect();
if (observeRef.current) {
observeRef.current.disconnect();
observeRef.current = null;
}
};
}, [targetEl, options]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [targetEl, signalRen.current]);
}

0 comments on commit 6089140

Please sign in to comment.