fix cleanUp in useEffect

This commit is contained in:
fantasticit 2023-01-08 14:40:56 +08:00
parent a8c338b6ef
commit 00a6d034ba
5 changed files with 75 additions and 15 deletions

View File

@ -23,6 +23,10 @@ export const useEditor = (options: Partial<EditorOptions> = {}, deps: Dependency
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();
useEffect(() => { useEffect(() => {
let isUnmount = false;
let timer1: ReturnType<typeof requestAnimationFrame> = null;
let timer2: ReturnType<typeof requestAnimationFrame> = null;
options.editorProps = options.editorProps || {}; options.editorProps = options.editorProps || {};
if (options.editable) { if (options.editable) {
@ -49,14 +53,22 @@ export const useEditor = (options: Partial<EditorOptions> = {}, deps: Dependency
} }
instance.on('transaction', () => { instance.on('transaction', () => {
requestAnimationFrame(() => { if (!isUnmount) {
requestAnimationFrame(() => { timer1 = requestAnimationFrame(() => {
forceUpdate(); timer2 = requestAnimationFrame(() => {
forceUpdate();
});
}); });
}); } else {
cancelAnimationFrame(timer1);
cancelAnimationFrame(timer2);
}
}); });
return () => { return () => {
cancelAnimationFrame(timer1);
cancelAnimationFrame(timer2);
isUnmount = true;
instance.destroy(); instance.destroy();
}; };
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps

View File

@ -45,27 +45,44 @@ export const _ExcalidrawWrapper = ({ editor, node, updateAttributes }) => {
); );
useEffect(() => { useEffect(() => {
let isUnmount = false;
import('@excalidraw/excalidraw') import('@excalidraw/excalidraw')
.then((res) => { .then((res) => {
exportToSvgRef.current = res.exportToSvg; if (!isUnmount) {
exportToSvgRef.current = res.exportToSvg;
}
}) })
.catch(setError) .catch((err) => !isUnmount && setError(err))
.finally(() => toggleLoading(false)); .finally(() => !isUnmount && toggleLoading(false));
return () => {
isUnmount = true;
};
}, [toggleLoading, data]); }, [toggleLoading, data]);
useEffect(() => { useEffect(() => {
let isUnmount = false;
const setContent = async () => { const setContent = async () => {
if (loading || error || !visible || !data) return; if (isUnmount || loading || error || !visible || !data) return;
const svg: SVGElement = await exportToSvgRef.current(data); const svg: SVGElement = await exportToSvgRef.current(data);
if (isUnmount) return;
svg.setAttribute('width', '100%'); svg.setAttribute('width', '100%');
svg.setAttribute('height', '100%'); svg.setAttribute('height', '100%');
svg.setAttribute('display', 'block'); svg.setAttribute('display', 'block');
setSvg(svg); setSvg(svg);
}; };
setContent(); setContent();
return () => {
isUnmount = true;
};
}, [data, loading, error, visible]); }, [data, loading, error, visible]);
return ( return (

View File

@ -91,9 +91,15 @@ export const _FlowWrapper = ({ editor, node, updateAttributes }) => {
); );
useEffect(() => { useEffect(() => {
let isUnmount = false;
load() load()
.catch(setError) .catch((err) => !isUnmount && setError(err))
.finally(() => toggleLoading(false)); .finally(() => !isUnmount && toggleLoading(false));
return () => {
isUnmount = true;
};
}, [toggleLoading, data]); }, [toggleLoading, data]);
return ( return (

View File

@ -20,6 +20,7 @@ const INHERIT_SIZE_STYLE = { width: '100%', height: '100%', maxWidth: '100%' };
export const _MindWrapper = ({ editor, node, updateAttributes }) => { export const _MindWrapper = ({ editor, node, updateAttributes }) => {
const $mind = useRef(null); const $mind = useRef(null);
const $centerTimer = useRef<ReturnType<typeof setTimeout>>(null);
const isEditable = editor.isEditable; const isEditable = editor.isEditable;
const { width: maxWidth } = getEditorContainerDOMSize(editor); const { width: maxWidth } = getEditorContainerDOMSize(editor);
const { data, width, height } = node.attrs; const { data, width, height } = node.attrs;
@ -46,7 +47,7 @@ export const _MindWrapper = ({ editor, node, updateAttributes }) => {
const onResize = useCallback( const onResize = useCallback(
(size) => { (size) => {
updateAttributes({ width: size.width, height: size.height }); updateAttributes({ width: size.width, height: size.height });
setTimeout(() => { $centerTimer.current = setTimeout(() => {
setCenter(); setCenter();
}); });
}, },
@ -86,9 +87,15 @@ export const _MindWrapper = ({ editor, node, updateAttributes }) => {
); );
useEffect(() => { useEffect(() => {
let isUnmount = false;
load() load()
.catch(setError) .catch((err) => !isUnmount && setError(err))
.finally(() => toggleLoading(false)); .finally(() => !isUnmount && toggleLoading(false));
return () => {
isUnmount = true;
};
}, [toggleLoading]); }, [toggleLoading]);
// 数据同步渲染 // 数据同步渲染
@ -105,6 +112,12 @@ export const _MindWrapper = ({ editor, node, updateAttributes }) => {
setCenter(); setCenter();
}, [width, height, setCenter]); }, [width, height, setCenter]);
useEffect(() => {
return () => {
clearTimeout($centerTimer.current);
};
}, []);
return ( return (
<NodeViewWrapper className={cls(styles.wrap)}> <NodeViewWrapper className={cls(styles.wrap)}>
<VisibilitySensor onChange={onViewportChange}> <VisibilitySensor onChange={onViewportChange}>

View File

@ -56,20 +56,32 @@ export const StatusWrapper = ({ editor, node, updateAttributes }) => {
); );
useEffect(() => { useEffect(() => {
let timer: ReturnType<typeof setTimeout> = null;
if (defaultShowPicker && user && user.id === createUser) { if (defaultShowPicker && user && user.id === createUser) {
toggleVisible(true); toggleVisible(true);
setTimeout(() => ref.current?.focus(), 200); timer = setTimeout(() => ref.current?.focus(), 200);
} }
return () => {
clearTimeout(timer);
};
}, [defaultShowPicker, toggleVisible, createUser, user]); }, [defaultShowPicker, toggleVisible, createUser, user]);
useEffect(() => { useEffect(() => {
let timer: ReturnType<typeof setTimeout> = null;
if (visible) { if (visible) {
setTimeout(() => { timer = setTimeout(() => {
ref.current?.focus(); ref.current?.focus();
}, 200); }, 200);
} else { } else {
updateAttributes({ text: currentText }); updateAttributes({ text: currentText });
} }
return () => {
clearTimeout(timer);
};
}, [visible, updateAttributes, currentText]); }, [visible, updateAttributes, currentText]);
return ( return (