From 101a28d01d04f21d46bf2b1ba46c8f716b9631f0 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Tue, 3 Aug 2021 19:02:59 +0300 Subject: [PATCH] [Teact] [Dev] Add more debug tools --- src/hooks/useEffectWithPrevDeps.ts | 4 +- src/hooks/useLayoutEffectWithPrevDeps.ts | 6 +-- src/lib/teact/teact.ts | 62 ++++++++++++++++-------- src/util/arePropsShallowEqual.ts | 8 ++- 4 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/hooks/useEffectWithPrevDeps.ts b/src/hooks/useEffectWithPrevDeps.ts index ba88fbb98..44ab6cd78 100644 --- a/src/hooks/useEffectWithPrevDeps.ts +++ b/src/hooks/useEffectWithPrevDeps.ts @@ -1,11 +1,11 @@ import { useEffect } from '../lib/teact/teact'; import usePrevious from './usePrevious'; -export default (cb: (args: PT) => void, dependencies: T) => { +export default (cb: (args: PT) => void, dependencies: T, debugKey?: string) => { const prevDeps = usePrevious(dependencies); return useEffect(() => { // @ts-ignore (workaround for "could be instantiated with a different subtype" issue) return cb(prevDeps || []); // eslint-disable-next-line react-hooks/exhaustive-deps - }, dependencies); + }, dependencies, debugKey); }; diff --git a/src/hooks/useLayoutEffectWithPrevDeps.ts b/src/hooks/useLayoutEffectWithPrevDeps.ts index a61cd0dff..53d8b2c0b 100644 --- a/src/hooks/useLayoutEffectWithPrevDeps.ts +++ b/src/hooks/useLayoutEffectWithPrevDeps.ts @@ -1,11 +1,11 @@ import { useLayoutEffect } from '../lib/teact/teact'; import usePrevious from './usePrevious'; -export default (cb: (args: PT) => void, dependencies: T) => { +export default (cb: (args: PT) => void, dependencies: T, debugKey?: string) => { const prevDeps = usePrevious(dependencies); return useLayoutEffect(() => { // @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 - }, dependencies); + }, dependencies, debugKey); }; diff --git a/src/lib/teact/teact.ts b/src/lib/teact/teact.ts index c98b02a41..351cb7410 100644 --- a/src/lib/teact/teact.ts +++ b/src/lib/teact/teact.ts @@ -9,7 +9,9 @@ import { removeAllDelegatedListeners } from './dom-events'; export type Props = AnyLiteral; export type FC

= (props: P) => any; -export type FC_withDebug = FC & { +export type FC_withDebug = + FC + & { DEBUG_contentComponentName?: string; }; @@ -477,17 +479,19 @@ export function useState(initial?: T): [T, StateHookSetter] { componentInstance.forceUpdate(); if (DEBUG_MORE) { - // eslint-disable-next-line no-console - console.log( - '[Teact.useState]', - componentInstance.name, - // `componentInstance.Component` may be set to `null` by GC helper - componentInstance.Component && (componentInstance.Component as FC_withDebug).DEBUG_contentComponentName - ? `> ${(componentInstance.Component as FC_withDebug).DEBUG_contentComponentName}` - : '', - `Forced update at cursor #${cursor}, next value: `, - byCursor[cursor].nextValue, - ); + if (componentInstance.name !== 'TeactNContainer') { + // eslint-disable-next-line no-console + console.log( + '[Teact.useState]', + componentInstance.name, + // `componentInstance.Component` may be set to `null` by GC helper + componentInstance.Component && (componentInstance.Component as FC_withDebug).DEBUG_contentComponentName + ? `> ${(componentInstance.Component as FC_withDebug).DEBUG_contentComponentName}` + : '', + `Forced update at cursor #${cursor}, next value: `, + byCursor[cursor].nextValue, + ); + } } } })(renderingInstance), @@ -506,6 +510,7 @@ function useLayoutEffectBase( schedulerFn: typeof onTickEnd | typeof requestAnimationFrame, effect: () => Function | void, dependencies?: any[], + debugKey?: string, ) { const { cursor, byCursor } = renderingInstance.hooks.effects; const componentInstance = renderingInstance; @@ -529,6 +534,25 @@ function useLayoutEffectBase( if (byCursor[cursor] !== undefined && dependencies && byCursor[cursor].dependencies) { 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); } } else { @@ -544,12 +568,12 @@ function useLayoutEffectBase( renderingInstance.hooks.effects.cursor++; } -export function useEffect(effect: () => Function | void, dependencies?: any[]) { - return useLayoutEffectBase(fastRaf, effect, dependencies); +export function useEffect(effect: () => Function | void, dependencies?: any[], debugKey?: string) { + return useLayoutEffectBase(fastRaf, effect, dependencies, debugKey); } -export function useLayoutEffect(effect: () => Function | void, dependencies?: any[]) { - return useLayoutEffectBase(onTickEnd, effect, dependencies); +export function useLayoutEffect(effect: () => Function | void, dependencies?: any[], debugKey?: string) { + return useLayoutEffectBase(onTickEnd, effect, dependencies, debugKey); } export function useMemo(resolver: () => T, dependencies: any[], debugKey?: string): T { @@ -599,17 +623,17 @@ export function useRef(initial?: T | null) { }), []); } -export function memo(Component: T, areEqual = arePropsShallowEqual, withDebug = false) { +export function memo(Component: T, areEqual = arePropsShallowEqual, debugKey?: string) { return function TeactMemoWrapper(props: Props) { // eslint-disable-next-line react-hooks/rules-of-hooks const propsRef = useRef(props); const renderedRef = useRef(); if (!renderedRef.current || (propsRef.current && !areEqual(propsRef.current, props))) { - if (DEBUG && withDebug) { + if (DEBUG && debugKey) { // eslint-disable-next-line no-console console.log( - `[Teact.memo] ${Component.name}: Update is caused by:`, + `[Teact.memo] ${Component.name} (${debugKey}): Update is caused by:`, getUnequalProps(propsRef.current!, props).join(', '), ); } diff --git a/src/util/arePropsShallowEqual.ts b/src/util/arePropsShallowEqual.ts index ac702087b..ade4c4640 100644 --- a/src/util/arePropsShallowEqual.ts +++ b/src/util/arePropsShallowEqual.ts @@ -34,5 +34,11 @@ export function getUnequalProps(currentProps: AnyLiteral, newProps: AnyLiteral) 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[]); }