From a17240466aa6306e84a61e6643059d0d1a0c0158 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Sun, 9 May 2021 02:00:00 +0300 Subject: [PATCH] [Debug] Some more debug tools --- src/lib/teact/teact.ts | 33 ++++++++++++++++++++++++++++++-- src/lib/teact/teactn.tsx | 18 ++++------------- src/util/arePropsShallowEqual.ts | 12 ++++++++++++ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/lib/teact/teact.ts b/src/lib/teact/teact.ts index 87066357d..8c2b71cc1 100644 --- a/src/lib/teact/teact.ts +++ b/src/lib/teact/teact.ts @@ -3,12 +3,15 @@ import { fastRaf, onTickEnd, throttleWithPrimaryRaf, throttleWithRaf, } from '../../util/schedulers'; import { flatten, orderBy } from '../../util/iteratees'; -import arePropsShallowEqual from '../../util/arePropsShallowEqual'; +import arePropsShallowEqual, { getUnequalProps } from '../../util/arePropsShallowEqual'; import { handleError } from '../../util/handleError'; import { removeAllDelegatedListeners } from './dom-events'; export type Props = AnyLiteral; export type FC

= (props: P) => any; +export type FC_withDebug = FC & { + DEBUG_contentComponentName?: string; +}; export enum VirtualElementTypesEnum { Empty, @@ -444,6 +447,10 @@ export function useState(initial?: T): [T, StateHookSetter] { value: initial, nextValue: initial, setter: ((componentInstance) => (newValue: ((current: T) => T) | T) => { + if (!componentInstance.isMounted) { + return; + } + if (byCursor[cursor].nextValue !== newValue) { byCursor[cursor].nextValue = typeof newValue === 'function' ? (newValue as (current: T) => T)(byCursor[cursor].value) @@ -454,6 +461,20 @@ export function useState(initial?: T): [T, StateHookSetter] { componentInstance.forceUpdate = throttleWithRaf(() => forceUpdateComponent(componentInstance)); } + if (DEBUG_MORE) { + // eslint-disable-next-line no-console + console.log( + '[Teact.useState]', + componentInstance.name, + // eslint-disable-next-line max-len + (componentInstance.Component as FC_withDebug).DEBUG_contentComponentName + ? `> ${(componentInstance.Component as FC_withDebug).DEBUG_contentComponentName}` + : '', + `Forced update at cursor #${cursor}, next value: `, + byCursor[cursor].nextValue, + ); + } + componentInstance.scheduleNextState(); componentInstance.forceUpdate(); } @@ -556,13 +577,21 @@ export function useRef(initial?: T | null) { }), []); } -export function memo(Component: T, areEqual = arePropsShallowEqual) { +export function memo(Component: T, areEqual = arePropsShallowEqual, withDebug = false) { 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) { + // eslint-disable-next-line no-console + console.log( + `[Teact.memo] ${Component.name}: Update is caused by:`, + getUnequalProps(propsRef.current!, props).join(', '), + ); + } + propsRef.current = props; renderedRef.current = createElement(Component, props) as VirtualElementComponent; } diff --git a/src/lib/teact/teactn.tsx b/src/lib/teact/teactn.tsx index 2d910855f..1b003db8b 100644 --- a/src/lib/teact/teactn.tsx +++ b/src/lib/teact/teactn.tsx @@ -1,12 +1,12 @@ import React, { - FC, Props, useEffect, useState, + FC, FC_withDebug, Props, useEffect, useState, } from './teact'; import { DEBUG, DEBUG_MORE } from '../../config'; import useForceUpdate from '../../hooks/useForceUpdate'; import generateIdFor from '../../util/generateIdFor'; import { throttleWithRaf } from '../../util/schedulers'; -import arePropsShallowEqual from '../../util/arePropsShallowEqual'; +import arePropsShallowEqual, { getUnequalProps } from '../../util/arePropsShallowEqual'; import { orderBy } from '../../util/iteratees'; import { GlobalState, GlobalActions, ActionTypes } from '../../global/types'; import { handleError } from '../../util/handleError'; @@ -164,6 +164,8 @@ export function withGlobal( ) { return (Component: FC) => { return function TeactNContainer(props: OwnProps) { + (TeactNContainer as FC_withDebug).DEBUG_contentComponentName = Component.name; + const [id] = useState(generateIdFor(containers)); const forceUpdate = useForceUpdate(); @@ -211,18 +213,6 @@ export function withGlobal( }; } -function getUnequalProps(currentProps: AnyLiteral, newProps: AnyLiteral) { - const currentKeys = Object.keys(currentProps); - const currentKeysLength = currentKeys.length; - const newKeysLength = Object.keys(newProps).length; - - if (currentKeysLength !== newKeysLength) { - return ['LENGTH']; - } - - return currentKeys.filter((prop) => currentProps[prop] !== newProps[prop]); -} - if (DEBUG) { (window as any).getGlobal = getGlobal; diff --git a/src/util/arePropsShallowEqual.ts b/src/util/arePropsShallowEqual.ts index 0568e8269..ac702087b 100644 --- a/src/util/arePropsShallowEqual.ts +++ b/src/util/arePropsShallowEqual.ts @@ -24,3 +24,15 @@ export default function arePropsShallowEqual(currentProps: AnyLiteral, newProps: return true; } + +export function getUnequalProps(currentProps: AnyLiteral, newProps: AnyLiteral) { + const currentKeys = Object.keys(currentProps); + const currentKeysLength = currentKeys.length; + const newKeysLength = Object.keys(newProps).length; + + if (currentKeysLength !== newKeysLength) { + return ['%LENGTH%']; + } + + return currentKeys.filter((prop) => currentProps[prop] !== newProps[prop]); +}