[Teact] [Dev] Add more debug tools

This commit is contained in:
Alexander Zinchuk 2021-08-03 19:02:59 +03:00
parent 8badc07b0e
commit 101a28d01d
4 changed files with 55 additions and 25 deletions

View File

@ -1,11 +1,11 @@
import { useEffect } from '../lib/teact/teact'; import { useEffect } from '../lib/teact/teact';
import usePrevious from './usePrevious'; import usePrevious from './usePrevious';
export default <T extends any[], PT = T>(cb: (args: PT) => void, dependencies: T) => { export default <T extends any[], PT = T>(cb: (args: PT) => void, dependencies: T, debugKey?: string) => {
const prevDeps = usePrevious<T>(dependencies); const prevDeps = usePrevious<T>(dependencies);
return useEffect(() => { return useEffect(() => {
// @ts-ignore (workaround for "could be instantiated with a different subtype" issue) // @ts-ignore (workaround for "could be instantiated with a different subtype" issue)
return cb(prevDeps || []); return cb(prevDeps || []);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, dependencies); }, dependencies, debugKey);
}; };

View File

@ -1,11 +1,11 @@
import { useLayoutEffect } from '../lib/teact/teact'; import { useLayoutEffect } from '../lib/teact/teact';
import usePrevious from './usePrevious'; import usePrevious from './usePrevious';
export default <T extends any[], PT = T>(cb: (args: PT) => void, dependencies: T) => { export default <T extends any[], PT = T>(cb: (args: PT) => void, dependencies: T, debugKey?: string) => {
const prevDeps = usePrevious<T>(dependencies); const prevDeps = usePrevious<T>(dependencies);
return useLayoutEffect(() => { return useLayoutEffect(() => {
// @ts-ignore (workaround for "could be instantiated with a different subtype" issue) // @ts-ignore (workaround for "could be instantiated with a different subtype" issue)
cb(prevDeps || []); return cb(prevDeps || []);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, dependencies); }, dependencies, debugKey);
}; };

View File

@ -9,7 +9,9 @@ import { removeAllDelegatedListeners } from './dom-events';
export type Props = AnyLiteral; export type Props = AnyLiteral;
export type FC<P extends Props = any> = (props: P) => any; export type FC<P extends Props = any> = (props: P) => any;
export type FC_withDebug = FC & { export type FC_withDebug =
FC
& {
DEBUG_contentComponentName?: string; DEBUG_contentComponentName?: string;
}; };
@ -477,6 +479,7 @@ export function useState<T>(initial?: T): [T, StateHookSetter<T>] {
componentInstance.forceUpdate(); componentInstance.forceUpdate();
if (DEBUG_MORE) { if (DEBUG_MORE) {
if (componentInstance.name !== 'TeactNContainer') {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log( console.log(
'[Teact.useState]', '[Teact.useState]',
@ -490,6 +493,7 @@ export function useState<T>(initial?: T): [T, StateHookSetter<T>] {
); );
} }
} }
}
})(renderingInstance), })(renderingInstance),
}; };
} }
@ -506,6 +510,7 @@ function useLayoutEffectBase(
schedulerFn: typeof onTickEnd | typeof requestAnimationFrame, schedulerFn: typeof onTickEnd | typeof requestAnimationFrame,
effect: () => Function | void, effect: () => Function | void,
dependencies?: any[], dependencies?: any[],
debugKey?: string,
) { ) {
const { cursor, byCursor } = renderingInstance.hooks.effects; const { cursor, byCursor } = renderingInstance.hooks.effects;
const componentInstance = renderingInstance; const componentInstance = renderingInstance;
@ -529,6 +534,25 @@ function useLayoutEffectBase(
if (byCursor[cursor] !== undefined && dependencies && byCursor[cursor].dependencies) { if (byCursor[cursor] !== undefined && dependencies && byCursor[cursor].dependencies) {
if (dependencies.some((dependency, i) => dependency !== byCursor[cursor].dependencies![i])) { if (dependencies.some((dependency, i) => dependency !== byCursor[cursor].dependencies![i])) {
if (debugKey) {
const causedBy = dependencies.reduce((res, newValue, i) => {
const prevValue = byCursor[cursor].dependencies![i];
if (newValue !== prevValue) {
res.push(`${i}: ${prevValue} => ${newValue}`);
}
return res;
}, []);
// eslint-disable-next-line no-console
console.log(
'[Teact]',
debugKey,
'Effect caused by dependencies.',
causedBy.join(', '),
);
}
schedulerFn(exec); schedulerFn(exec);
} }
} else { } else {
@ -544,12 +568,12 @@ function useLayoutEffectBase(
renderingInstance.hooks.effects.cursor++; renderingInstance.hooks.effects.cursor++;
} }
export function useEffect(effect: () => Function | void, dependencies?: any[]) { export function useEffect(effect: () => Function | void, dependencies?: any[], debugKey?: string) {
return useLayoutEffectBase(fastRaf, effect, dependencies); return useLayoutEffectBase(fastRaf, effect, dependencies, debugKey);
} }
export function useLayoutEffect(effect: () => Function | void, dependencies?: any[]) { export function useLayoutEffect(effect: () => Function | void, dependencies?: any[], debugKey?: string) {
return useLayoutEffectBase(onTickEnd, effect, dependencies); return useLayoutEffectBase(onTickEnd, effect, dependencies, debugKey);
} }
export function useMemo<T extends any>(resolver: () => T, dependencies: any[], debugKey?: string): T { export function useMemo<T extends any>(resolver: () => T, dependencies: any[], debugKey?: string): T {
@ -599,17 +623,17 @@ export function useRef<T>(initial?: T | null) {
}), []); }), []);
} }
export function memo<T extends FC>(Component: T, areEqual = arePropsShallowEqual, withDebug = false) { export function memo<T extends FC>(Component: T, areEqual = arePropsShallowEqual, debugKey?: string) {
return function TeactMemoWrapper(props: Props) { return function TeactMemoWrapper(props: Props) {
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks
const propsRef = useRef(props); const propsRef = useRef(props);
const renderedRef = useRef(); const renderedRef = useRef();
if (!renderedRef.current || (propsRef.current && !areEqual(propsRef.current, props))) { if (!renderedRef.current || (propsRef.current && !areEqual(propsRef.current, props))) {
if (DEBUG && withDebug) { if (DEBUG && debugKey) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log( console.log(
`[Teact.memo] ${Component.name}: Update is caused by:`, `[Teact.memo] ${Component.name} (${debugKey}): Update is caused by:`,
getUnequalProps(propsRef.current!, props).join(', '), getUnequalProps(propsRef.current!, props).join(', '),
); );
} }

View File

@ -34,5 +34,11 @@ export function getUnequalProps(currentProps: AnyLiteral, newProps: AnyLiteral)
return ['%LENGTH%']; return ['%LENGTH%'];
} }
return currentKeys.filter((prop) => currentProps[prop] !== newProps[prop]); return currentKeys.reduce((res, prop) => {
if (currentProps[prop] !== newProps[prop]) {
res.push(`${prop}: ${currentProps[prop]} => ${newProps[prop]}`);
}
return res;
}, [] as string[]);
} }