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]);
+}