[Perf] useVideoCleanup: Remove event listeners
This commit is contained in:
parent
9ad5cf4909
commit
af9d8695f4
@ -181,7 +181,8 @@ const VideoPlayer: FC<OwnProps> = ({
|
||||
}
|
||||
});
|
||||
|
||||
useVideoCleanup(videoRef, []);
|
||||
useVideoCleanup(videoRef, bufferingHandlers);
|
||||
|
||||
const [, setCurrentTime] = useCurrentTimeSignal();
|
||||
const [, setIsVideoWaiting] = useVideoWaitingSignal();
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@ function OptimizedVideo({
|
||||
}
|
||||
|
||||
const { handlePlaying: handlePlayingForAutoPause } = useVideoAutoPause(ref, canPlay, isPriority);
|
||||
useVideoCleanup(ref, []);
|
||||
|
||||
const isReadyRef = useRef(false);
|
||||
const handleReady = useLastCallback(() => {
|
||||
@ -77,6 +76,8 @@ function OptimizedVideo({
|
||||
return mergedHandlers;
|
||||
}, [otherBufferingHandlers, restProps]);
|
||||
|
||||
useVideoCleanup(ref, mergedOtherBufferingHandlers);
|
||||
|
||||
return (
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
<video ref={ref} autoPlay {...restProps} {...mergedOtherBufferingHandlers} onPlaying={handlePlaying}>
|
||||
|
||||
@ -1,20 +1,31 @@
|
||||
import type { RefObject } from 'react';
|
||||
import { onFullyIdle, useEffect } from '../lib/teact/teact';
|
||||
import { resolveEventType } from '../lib/teact/dom-events';
|
||||
import { onFullyIdle, useLayoutEffect } from '../lib/teact/teact';
|
||||
|
||||
import unloadVideo from '../util/browser/unloadVideo';
|
||||
import { useStateRef } from './useStateRef';
|
||||
|
||||
// Fix for memory leak when unmounting video element
|
||||
export default function useVideoCleanup(videoRef: RefObject<HTMLVideoElement>, dependencies: any[]) {
|
||||
useEffect(() => {
|
||||
// Fix memory leak when unmounting video element
|
||||
export default function useVideoCleanup(videoRef: RefObject<HTMLVideoElement>, handlers?: Record<string, AnyFunction>) {
|
||||
const handlersRef = useStateRef(handlers);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const videoEl = videoRef.current;
|
||||
if (!videoEl) return undefined;
|
||||
|
||||
return () => {
|
||||
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
|
||||
const handlers2 = handlersRef.current;
|
||||
if (handlers2) {
|
||||
Object.entries(handlers2).forEach(([key, value]) => {
|
||||
videoEl.removeEventListener(resolveEventType(key, videoEl), value, false);
|
||||
});
|
||||
}
|
||||
|
||||
// It may be slow (specifically on iOS), so we postpone it after unmounting
|
||||
onFullyIdle(() => {
|
||||
unloadVideo(videoEl);
|
||||
});
|
||||
};
|
||||
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
|
||||
}, dependencies);
|
||||
}, [handlersRef, videoRef]);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ export function removeEventListener(element: Element, propName: string, handler:
|
||||
}
|
||||
}
|
||||
|
||||
function resolveEventType(propName: string, element: Element) {
|
||||
export function resolveEventType(propName: string, element: Element) {
|
||||
const eventType = propName
|
||||
.replace(/^on/, '')
|
||||
.replace(/Capture$/, '').toLowerCase();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user