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