1- import React , { createContext , useCallback , useContext , useEffect , useMemo , useState } from 'react' ;
1+ import { deepEqual } from 'fast-equals' ;
2+ import React , { createContext , useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react' ;
23import type { OnyxEntry } from 'react-native-onyx' ;
4+ import Log from '@libs/Log' ;
35import { getPolicyEmployeeListByIdWithoutCurrentUser } from '@libs/PolicyUtils' ;
46import SidebarUtils from '@libs/SidebarUtils' ;
57import CONST from '@src/CONST' ;
@@ -224,6 +226,53 @@ function SidebarOrderedReportsContextProvider({
224226 } ;
225227 } , [ getOrderedReportIDs , orderedReportIDs , derivedCurrentReportID , policyMemberAccountIDs , shouldUseNarrowLayout , getOrderedReports , orderedReports ] ) ;
226228
229+ const currentDeps = {
230+ priorityMode,
231+ chatReports,
232+ policies,
233+ transactions,
234+ transactionViolations,
235+ reportNameValuePairs,
236+ betas,
237+ reportAttributes,
238+ currentReportsToDisplay,
239+ shouldUseNarrowLayout,
240+ accountID,
241+ currentReportIDValue,
242+ derivedCurrentReportID,
243+ prevDerivedCurrentReportID,
244+ policyMemberAccountIDs,
245+ prevBetas,
246+ prevPriorityMode,
247+ reportsToDisplayInLHN,
248+ orderedReportIDs,
249+ orderedReports,
250+ } ;
251+ const prevContextValue = usePrevious ( contextValue ) ;
252+ const previousDeps = usePrevious ( currentDeps ) ;
253+ const firstRender = useRef ( true ) ;
254+
255+ useEffect ( ( ) => {
256+ // Cases below ensure we only log when the edge case (empty -> non-empty or non-empty -> empty) happens.
257+ // This is done to avoid excessive logging when the orderedReports array is updated, but does not impact LHN.
258+
259+ // Case 1: orderedReports goes from empty to non-empty
260+ if ( contextValue . orderedReports . length > 0 && prevContextValue ?. orderedReports . length === 0 ) {
261+ logChangedDeps ( '[useSidebarOrderedReports] Ordered reports went from empty to non-empty' , currentDeps , previousDeps ) ;
262+ }
263+ // Case 2: orderedReports goes from non-empty to empty
264+ if ( contextValue . orderedReports . length === 0 && prevContextValue ?. orderedReports . length > 0 ) {
265+ logChangedDeps ( '[useSidebarOrderedReports] Ordered reports went from non-empty to empty' , currentDeps , previousDeps ) ;
266+ }
267+
268+ // Case 3: orderedReports are empty from the beginning
269+ if ( firstRender . current && contextValue . orderedReports . length === 0 ) {
270+ logChangedDeps ( '[useSidebarOrderedReports] Ordered reports initialized empty' , currentDeps , previousDeps ) ;
271+ }
272+
273+ firstRender . current = false ;
274+ } ) ;
275+
227276 return < SidebarOrderedReportsContext . Provider value = { contextValue } > { children } </ SidebarOrderedReportsContext . Provider > ;
228277}
229278
@@ -233,3 +282,31 @@ function useSidebarOrderedReports() {
233282
234283export { SidebarOrderedReportsContext , SidebarOrderedReportsContextProvider , useSidebarOrderedReports } ;
235284export type { PartialPolicyForSidebar , ReportsToDisplayInLHN } ;
285+
286+ function getChangedKeys < T extends Record < string , unknown > > ( deps : T , prevDeps : T ) {
287+ const depsKeys = Object . keys ( deps ) ;
288+
289+ return depsKeys . filter ( ( depKey ) => ! deepEqual ( deps [ depKey ] , prevDeps [ depKey ] ) ) ;
290+ }
291+
292+ function logChangedDeps < T extends Record < string , unknown > > ( msg : string , deps : T , prevDeps : T ) {
293+ const startTime = performance . now ( ) ;
294+ const changedDeps = getChangedKeys ( deps , prevDeps ) ;
295+ const parsedDeps = parseDepsForLogging ( deps ) ;
296+ const processingDuration = performance . now ( ) - startTime ;
297+ Log . info ( msg , false , {
298+ deps : parsedDeps ,
299+ changedDeps,
300+ processingDuration,
301+ } ) ;
302+ }
303+
304+ /**
305+ * @param deps - The dependencies to parse.
306+ * @returns A simplified object with light-weight values.
307+ */
308+ function parseDepsForLogging < T extends Record < string , unknown > > ( deps : T ) {
309+ // If object or array, return the keys' length
310+ // If primitive, return the value
311+ return Object . fromEntries ( Object . entries ( deps ) . map ( ( [ key , value ] ) => [ key , typeof value === 'object' && value !== null ? Object . keys ( value ) . length : value ] ) ) ;
312+ }
0 commit comments