From a71e594e20575c7bca69fe3eac86cb6389037d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Fri, 11 Jul 2025 11:41:05 +0200 Subject: [PATCH 1/4] useSidebarOrderedReports: dependencies logging at edge-case --- src/hooks/useSidebarOrderedReports.tsx | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx index e6951ca4f5fd..415a5840784b 100644 --- a/src/hooks/useSidebarOrderedReports.tsx +++ b/src/hooks/useSidebarOrderedReports.tsx @@ -1,5 +1,7 @@ +import {deepEqual} from 'fast-equals'; import React, {createContext, useCallback, useContext, useEffect, useMemo, useState} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; +import Log from '@libs/Log'; import {getPolicyEmployeeListByIdWithoutCurrentUser} from '@libs/PolicyUtils'; import SidebarUtils from '@libs/SidebarUtils'; import CONST from '@src/CONST'; @@ -224,6 +226,45 @@ function SidebarOrderedReportsContextProvider({ }; }, [getOrderedReportIDs, orderedReportIDs, derivedCurrentReportID, policyMemberAccountIDs, shouldUseNarrowLayout, getOrderedReports, orderedReports]); + const currentDeps = { + priorityMode, + chatReports, + policies, + transactions, + transactionViolations, + reportNameValuePairs, + betas, + reportAttributes, + currentReportsToDisplay, + shouldUseNarrowLayout, + accountID, + currentReportIDValue, + derivedCurrentReportID, + prevDerivedCurrentReportID, + policyMemberAccountIDs, + prevBetas, + prevPriorityMode, + reportsToDisplayInLHN, + orderedReportIDs, + orderedReports, + }; + const prevContextValue = usePrevious(contextValue); + const previousDeps = usePrevious(currentDeps); + + useEffect(() => { + // Cases below ensure we only log when the edge case (empty -> non-empty or non-empty -> empty) happens. + // This is done to avoid excessive logging when the orderedReports array is updated, but does not impact LHN. + + // Case 1: orderedReports goes from empty to non-empty + if (contextValue.orderedReports.length > 0 && prevContextValue?.orderedReports.length === 0) { + logChangedDeps('[useSidebarOrderedReports] Ordered reports went from empty to non-empty', currentDeps, previousDeps); + } + // Case 2: orderedReports goes from non-empty to empty + if (contextValue.orderedReports.length === 0 && prevContextValue?.orderedReports.length > 0) { + logChangedDeps('[useSidebarOrderedReports] Ordered reports went from non-empty to empty', currentDeps, previousDeps); + } + }, [contextValue, currentDeps, prevContextValue, previousDeps]); + return {children}; } @@ -233,3 +274,19 @@ function useSidebarOrderedReports() { export {SidebarOrderedReportsContext, SidebarOrderedReportsContextProvider, useSidebarOrderedReports}; export type {PartialPolicyForSidebar, ReportsToDisplayInLHN}; + +function getChangedKeys>(deps: T, prevDeps: T) { + const depsKeys = Object.keys(deps); + + return depsKeys.filter((depKey) => !deepEqual(deps[depKey], prevDeps[depKey])); +} + +function logChangedDeps(msg: string, deps: Record, prevDeps: Record) { + const startTime = performance.now(); + const changedDeps = getChangedKeys(deps, prevDeps); + const processingDuration = performance.now() - startTime; + Log.info(msg, false, { + changedDeps, + processingDuration, + }); +} From b1bf533a31d6a8c24325fa1a1615bf630eef654a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Fri, 11 Jul 2025 11:51:08 +0200 Subject: [PATCH 2/4] fix linter --- src/hooks/useSidebarOrderedReports.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx index 415a5840784b..377ac1a16bbe 100644 --- a/src/hooks/useSidebarOrderedReports.tsx +++ b/src/hooks/useSidebarOrderedReports.tsx @@ -263,7 +263,7 @@ function SidebarOrderedReportsContextProvider({ if (contextValue.orderedReports.length === 0 && prevContextValue?.orderedReports.length > 0) { logChangedDeps('[useSidebarOrderedReports] Ordered reports went from non-empty to empty', currentDeps, previousDeps); } - }, [contextValue, currentDeps, prevContextValue, previousDeps]); + }); return {children}; } @@ -275,13 +275,13 @@ function useSidebarOrderedReports() { export {SidebarOrderedReportsContext, SidebarOrderedReportsContextProvider, useSidebarOrderedReports}; export type {PartialPolicyForSidebar, ReportsToDisplayInLHN}; -function getChangedKeys>(deps: T, prevDeps: T) { +function getChangedKeys>(deps: T, prevDeps: T) { const depsKeys = Object.keys(deps); return depsKeys.filter((depKey) => !deepEqual(deps[depKey], prevDeps[depKey])); } -function logChangedDeps(msg: string, deps: Record, prevDeps: Record) { +function logChangedDeps>(msg: string, deps: T, prevDeps: T) { const startTime = performance.now(); const changedDeps = getChangedKeys(deps, prevDeps); const processingDuration = performance.now() - startTime; From 7a9abc24bb18a742f7b6348cfc3a6768792261d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Fri, 11 Jul 2025 12:10:34 +0200 Subject: [PATCH 3/4] add deps logging --- src/hooks/useSidebarOrderedReports.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx index 377ac1a16bbe..b43c91e67edd 100644 --- a/src/hooks/useSidebarOrderedReports.tsx +++ b/src/hooks/useSidebarOrderedReports.tsx @@ -284,9 +284,21 @@ function getChangedKeys>(deps: T, prevDeps: T) function logChangedDeps>(msg: string, deps: T, prevDeps: T) { const startTime = performance.now(); const changedDeps = getChangedKeys(deps, prevDeps); + const parsedDeps = parseDepsForLogging(deps); const processingDuration = performance.now() - startTime; Log.info(msg, false, { + deps: parsedDeps, changedDeps, processingDuration, }); } + +/** + * @param deps - The dependencies to parse. + * @returns A simplified object with light-weight values. + */ +function parseDepsForLogging>(deps: T) { + // If object or array, return the keys' length + // If primitive, return the value + return Object.fromEntries(Object.entries(deps).map(([key, value]) => [key, typeof value === 'object' && value !== null ? Object.keys(value).length : value])); +} From 4c4835cc6fb9bcfe61264c8eea5d09f647b080c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Fri, 11 Jul 2025 12:14:14 +0200 Subject: [PATCH 4/4] add initialization logging --- src/hooks/useSidebarOrderedReports.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx index b43c91e67edd..ed55aacb5918 100644 --- a/src/hooks/useSidebarOrderedReports.tsx +++ b/src/hooks/useSidebarOrderedReports.tsx @@ -1,5 +1,5 @@ import {deepEqual} from 'fast-equals'; -import React, {createContext, useCallback, useContext, useEffect, useMemo, useState} from 'react'; +import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import Log from '@libs/Log'; import {getPolicyEmployeeListByIdWithoutCurrentUser} from '@libs/PolicyUtils'; @@ -250,6 +250,7 @@ function SidebarOrderedReportsContextProvider({ }; const prevContextValue = usePrevious(contextValue); const previousDeps = usePrevious(currentDeps); + const firstRender = useRef(true); useEffect(() => { // Cases below ensure we only log when the edge case (empty -> non-empty or non-empty -> empty) happens. @@ -263,6 +264,13 @@ function SidebarOrderedReportsContextProvider({ if (contextValue.orderedReports.length === 0 && prevContextValue?.orderedReports.length > 0) { logChangedDeps('[useSidebarOrderedReports] Ordered reports went from non-empty to empty', currentDeps, previousDeps); } + + // Case 3: orderedReports are empty from the beginning + if (firstRender.current && contextValue.orderedReports.length === 0) { + logChangedDeps('[useSidebarOrderedReports] Ordered reports initialized empty', currentDeps, previousDeps); + } + + firstRender.current = false; }); return {children};