[Perf] Teact: Introduce useUnmountCleanup to reduce redundant effects
This commit is contained in:
parent
1c40b9b514
commit
2f0eaf72df
@ -2,7 +2,11 @@ import type { RefObject } from 'react';
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, {
|
||||
getIsHeavyAnimating,
|
||||
memo, useEffect, useRef, useState,
|
||||
memo,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
useUnmountCleanup,
|
||||
} from '../../lib/teact/teact';
|
||||
|
||||
import type RLottieInstance from '../../lib/rlottie/RLottie';
|
||||
@ -118,11 +122,9 @@ const AnimatedSticker: FC<OwnProps> = ({
|
||||
}, [color, shouldUseColorFilter]);
|
||||
|
||||
const isUnmountedRef = useRef(false);
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
isUnmountedRef.current = true;
|
||||
};
|
||||
}, []);
|
||||
useUnmountCleanup(() => {
|
||||
isUnmountedRef.current = true;
|
||||
});
|
||||
|
||||
const init = useLastCallback(() => {
|
||||
if (
|
||||
@ -184,11 +186,9 @@ const AnimatedSticker: FC<OwnProps> = ({
|
||||
animation.setColor(rgbColor.current);
|
||||
}, [color, animation]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
animationRef.current?.removeView(viewId);
|
||||
};
|
||||
}, [viewId]);
|
||||
useUnmountCleanup(() => {
|
||||
animationRef.current?.removeView(viewId);
|
||||
});
|
||||
|
||||
const playAnimation = useLastCallback((shouldRestart = false) => {
|
||||
if (
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import { useEffect } from '../../../lib/teact/teact';
|
||||
import { useUnmountCleanup } from '../../../lib/teact/teact';
|
||||
|
||||
import { createSignal } from '../../../util/signals';
|
||||
|
||||
export const [getIsVideoWaiting, setIsVideoWaiting] = createSignal(false);
|
||||
|
||||
export default function useVideoWaitingSignal() {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setIsVideoWaiting(false);
|
||||
};
|
||||
}, []);
|
||||
useUnmountCleanup(() => {
|
||||
setIsVideoWaiting(false);
|
||||
});
|
||||
|
||||
return [getIsVideoWaiting, setIsVideoWaiting] as const;
|
||||
}
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import { useEffect } from '../../../lib/teact/teact';
|
||||
import { useUnmountCleanup } from '../../../lib/teact/teact';
|
||||
|
||||
import { createSignal } from '../../../util/signals';
|
||||
|
||||
const [getZoomChange, setZoomChange] = createSignal(1);
|
||||
|
||||
export default function useZoomChange() {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setZoomChange(1);
|
||||
};
|
||||
}, []);
|
||||
useUnmountCleanup(() => {
|
||||
setZoomChange(1);
|
||||
});
|
||||
|
||||
return [getZoomChange, setZoomChange] as const;
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import type { GlobalState } from '../../global/types';
|
||||
import type { Signal, SignalSetter } from '../../util/signals';
|
||||
|
||||
import { createSignal } from '../../util/signals';
|
||||
import useEffectOnce from '../useEffectOnce';
|
||||
import useSyncEffect from '../useSyncEffect';
|
||||
|
||||
/*
|
||||
This hook is a more performant variation of the standard React `useSelector` hook. It allows to:
|
||||
@ -31,24 +31,25 @@ addCallback((global: GlobalState) => {
|
||||
|
||||
function useSelectorSignal<T extends unknown>(selector: Selector<T>): Signal<T> {
|
||||
let state = bySelector.get(selector);
|
||||
|
||||
if (!state) {
|
||||
const [getter, setter] = createSignal(selector(getGlobal()));
|
||||
state = { clientsCount: 0, getter, setter };
|
||||
bySelector.set(selector, state);
|
||||
}
|
||||
|
||||
useEffectOnce(() => {
|
||||
state!.clientsCount++;
|
||||
useSyncEffect(() => {
|
||||
const state2 = bySelector.get(selector)!;
|
||||
|
||||
state2.clientsCount++;
|
||||
|
||||
return () => {
|
||||
state!.clientsCount--;
|
||||
state2.clientsCount--;
|
||||
|
||||
if (!state!.clientsCount) {
|
||||
if (!state2.clientsCount) {
|
||||
bySelector.delete(selector);
|
||||
}
|
||||
};
|
||||
});
|
||||
}, [selector]);
|
||||
|
||||
return state.getter as Signal<T>;
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import { useEffect } from '../lib/teact/teact';
|
||||
import { useUnmountCleanup } from '../lib/teact/teact';
|
||||
|
||||
import { createSignal } from '../util/signals';
|
||||
|
||||
export const [getCurrentTime, setCurrentTime] = createSignal(0);
|
||||
|
||||
export default function useCurrentTimeSignal() {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setCurrentTime(0);
|
||||
};
|
||||
}, []);
|
||||
useUnmountCleanup(() => {
|
||||
setCurrentTime(0);
|
||||
});
|
||||
|
||||
return [getCurrentTime, setCurrentTime] as const;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useRef } from '../lib/teact/teact';
|
||||
import { useCallback, useRef, useUnmountCleanup } from '../lib/teact/teact';
|
||||
|
||||
const DEFAULT_THRESHOLD = 250;
|
||||
|
||||
@ -41,11 +41,9 @@ function useLongPress({
|
||||
window.clearTimeout(timerId.current);
|
||||
}, [onEnd, onClick]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
window.clearTimeout(timerId.current);
|
||||
};
|
||||
}, []);
|
||||
useUnmountCleanup(() => {
|
||||
window.clearTimeout(timerId.current);
|
||||
});
|
||||
|
||||
return {
|
||||
onMouseDown: start,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useRef } from '../lib/teact/teact';
|
||||
import { useRef, useUnmountCleanup } from '../lib/teact/teact';
|
||||
|
||||
import { cleanupEffect, isSignal } from '../util/signals';
|
||||
import useEffectOnce from './useEffectOnce';
|
||||
|
||||
export function useSignalEffect(effect: NoneToVoidFunction, dependencies: readonly any[]) {
|
||||
// The is extracted from `useEffectOnce` to run before all effects
|
||||
@ -16,9 +15,7 @@ export function useSignalEffect(effect: NoneToVoidFunction, dependencies: readon
|
||||
});
|
||||
}
|
||||
|
||||
useEffectOnce(() => {
|
||||
return () => {
|
||||
cleanupEffect(effect);
|
||||
};
|
||||
useUnmountCleanup(() => {
|
||||
cleanupEffect(effect);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { useRef } from '../lib/teact/teact';
|
||||
import { useRef, useUnmountCleanup } from '../lib/teact/teact';
|
||||
|
||||
import useEffectOnce from './useEffectOnce';
|
||||
import usePreviousDeprecated from './usePreviousDeprecated';
|
||||
|
||||
export default function useSyncEffect<const T extends readonly any[]>(
|
||||
@ -15,9 +14,7 @@ export default function useSyncEffect<const T extends readonly any[]>(
|
||||
cleanupRef.current = effect(prevDeps || []) ?? undefined;
|
||||
}
|
||||
|
||||
useEffectOnce(() => {
|
||||
return () => {
|
||||
cleanupRef.current?.();
|
||||
};
|
||||
useUnmountCleanup(() => {
|
||||
cleanupRef.current?.();
|
||||
});
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ interface ComponentInstance {
|
||||
cursor: number;
|
||||
byCursor: {
|
||||
dependencies?: readonly any[];
|
||||
schedule: NoneToVoidFunction;
|
||||
schedule?: NoneToVoidFunction;
|
||||
cleanup?: NoneToVoidFunction;
|
||||
releaseSignals?: NoneToVoidFunction;
|
||||
}[];
|
||||
@ -778,7 +778,7 @@ function useEffectBase(
|
||||
console.log(`[Teact] Effect "${debugKey}" caused by signal #${i} new value:`, signal());
|
||||
}
|
||||
|
||||
byCursor[cursor].schedule();
|
||||
byCursor[cursor].schedule!();
|
||||
}));
|
||||
|
||||
if (!cleanups?.length) {
|
||||
@ -807,6 +807,26 @@ export function useLayoutEffect(effect: Effect, dependencies?: readonly any[], d
|
||||
return useEffectBase(true, effect, dependencies, debugKey);
|
||||
}
|
||||
|
||||
export function useUnmountCleanup(cleanup: NoneToVoidFunction) {
|
||||
if (!renderingInstance.hooks) {
|
||||
renderingInstance.hooks = {};
|
||||
}
|
||||
|
||||
if (!renderingInstance.hooks.effects) {
|
||||
renderingInstance.hooks.effects = { cursor: 0, byCursor: [] };
|
||||
}
|
||||
|
||||
const { cursor, byCursor } = renderingInstance.hooks.effects;
|
||||
|
||||
if (!byCursor[cursor]) {
|
||||
byCursor[cursor] = {
|
||||
cleanup,
|
||||
};
|
||||
}
|
||||
|
||||
renderingInstance.hooks.effects.cursor++;
|
||||
}
|
||||
|
||||
export function useMemo<T extends any>(
|
||||
resolver: () => T,
|
||||
dependencies: any[],
|
||||
|
||||
@ -6,7 +6,7 @@ import { handleError } from '../../util/handleError';
|
||||
import { orderBy } from '../../util/iteratees';
|
||||
import { throttleWithTickEnd } from '../../util/schedulers';
|
||||
import { requestMeasure } from '../fasterdom/fasterdom';
|
||||
import React, { DEBUG_resolveComponentName, getIsHeavyAnimating, useEffect } from './teact';
|
||||
import React, { DEBUG_resolveComponentName, getIsHeavyAnimating, useUnmountCleanup } from './teact';
|
||||
|
||||
import useForceUpdate from '../../hooks/useForceUpdate';
|
||||
import useUniqueId from '../../hooks/useUniqueId';
|
||||
@ -255,11 +255,9 @@ export function withGlobal<OwnProps extends AnyLiteral>(
|
||||
const id = useUniqueId();
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
containers.delete(id);
|
||||
};
|
||||
}, [id]);
|
||||
useUnmountCleanup(() => {
|
||||
containers.delete(id);
|
||||
});
|
||||
|
||||
let container = containers.get(id)!;
|
||||
if (!container) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user