From 00eaed184b94b33337b47c1bd51de7a254387db5 Mon Sep 17 00:00:00 2001 From: N Date: Thu, 2 Jan 2025 07:08:58 +0900 Subject: [PATCH] init prev value --- CHANGELOG.md | 4 ++ src/hooks/useThrottledContext.ts | 16 +++--- src/services/ContextThrottleService.ts | 77 ++++++++++++++++++++------ src/utils/utils.ts | 11 ++++ 4 files changed, 84 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6948d86..6f01cac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +v1.7.3 +- +- Устранены проблемы при исползовании хука useParams c жестом SwipeBack. + v1.7.2 - - Устранены проблемы, связанные с работой runSync при использовании большого количества переходов в одной транзакции. diff --git a/src/hooks/useThrottledContext.ts b/src/hooks/useThrottledContext.ts index 9775cac..e1045d0 100644 --- a/src/hooks/useThrottledContext.ts +++ b/src/hooks/useThrottledContext.ts @@ -4,14 +4,11 @@ import { EventBus } from '../services/EventBus'; export function useThrottledContext(context: Context): [T, T | null] { const contextValue = useContext(context); - const contextName = context.displayName; - const [prevValue, setPrevValue] = useState(contextValue); - const [throttledValue, setThrottledValue] = useState(contextValue); + const contextName = context.displayName ?? ''; + const initialContextData = ContextThrottleService.retrieveContextInfo(contextName, contextValue); - if (!contextName) { - console.error('No context display name found'); - return [contextValue, null]; - } + const [prevValue, setPrevValue] = useState(initialContextData.prevValue); + const [throttledValue, setThrottledValue] = useState(initialContextData.throttledValue); useEffect(() => { const unsubscribe = EventBus.subscribe<(throttleValue: T, prevValue: T) => void>( @@ -29,5 +26,10 @@ export function useThrottledContext(context: Context): [T, T | null] { ContextThrottleService.triggerContextUpdate(contextName, contextValue); }, [contextValue, contextName]); + if (!contextName) { + console.error('No context display name found'); + return [contextValue, null]; + } + return [throttledValue, prevValue]; } diff --git a/src/services/ContextThrottleService.ts b/src/services/ContextThrottleService.ts index 146db69..f3fddb3 100644 --- a/src/services/ContextThrottleService.ts +++ b/src/services/ContextThrottleService.ts @@ -1,10 +1,11 @@ +import { areKeysEqual } from '../utils'; import { EventBus } from './EventBus'; import { TransactionExecutor } from './TransactionExecutor'; -interface ContextThrottleInfo { - prevValue: unknown; +interface ContextThrottleInfo { + prevValue: T | null; updateTimerId: number; - throttledValue: unknown; + throttledValue: T; lastUpdateTimestamp: number; } @@ -17,7 +18,7 @@ export class ContextThrottleService { private static instance?: ContextThrottleService; private interval = 0; private throttled = true; - private contextThrottleMap: Record = {}; + private contextThrottleMap: Map = new Map(); // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} @@ -30,20 +31,44 @@ export class ContextThrottleService { return ContextThrottleService.instance; } - private getContextThrottleInfoByName(contextName: string) { - if (!(contextName in this.contextThrottleMap)) { - this.contextThrottleMap[contextName] = { - prevValue: null, - throttledValue: null, - lastUpdateTimestamp: 0, - updateTimerId: 0, - }; + private validateContextInfo( + value: ContextThrottleInfo | undefined, + contextValue: T, + ): value is ContextThrottleInfo { + if (typeof value !== 'object' || typeof value.throttledValue !== typeof contextValue) { + return false; } - return this.contextThrottleMap[contextName]; + + if (typeof contextValue === 'object' && contextValue !== null) { + return areKeysEqual(value.throttledValue as object, contextValue); + } + + return true; + } + + private getContextThrottleInfoByName( + contextName: string, + contextValue: T, + ): ContextThrottleInfo { + const existingData = this.contextThrottleMap.get(contextName); + + if (this.validateContextInfo(existingData, contextValue)) { + return existingData; + } + + const newData: ContextThrottleInfo = { + prevValue: null, + throttledValue: contextValue, + lastUpdateTimestamp: 0, + updateTimerId: 0, + }; + + this.contextThrottleMap.set(contextName, newData); + return newData; } private isContextChange(contextName: string, newValue: T) { - const contextData = this.getContextThrottleInfoByName(contextName); + const contextData = this.getContextThrottleInfoByName(contextName, newValue); return !(newValue === contextData.throttledValue); } @@ -54,7 +79,12 @@ export class ContextThrottleService { } private updateContextValue(contextName: string, newValue: T) { - const contextData = this.getContextThrottleInfoByName(contextName); + const contextData = this.getContextThrottleInfoByName(contextName, newValue); + + if (!this.isContextChange(contextName, newValue)) { + return; + } + contextData.prevValue = contextData.throttledValue; contextData.lastUpdateTimestamp = Date.now(); contextData.throttledValue = newValue; @@ -62,9 +92,12 @@ export class ContextThrottleService { } private throttleUpdateContextValue(contextName: string, newValue: T) { - const contextData = this.getContextThrottleInfoByName(contextName); + const contextData = this.getContextThrottleInfoByName(contextName, newValue); clearTimeout(contextData.updateTimerId); - if (this.isRunSyncActive()) return; + + if (this.isRunSyncActive()) { + return; + } const lastUpdateTimestamp = contextData.lastUpdateTimestamp; const timeUntilNextUpdate = this.getTimeUntilNextUpdate(lastUpdateTimestamp); @@ -96,6 +129,16 @@ export class ContextThrottleService { } } + public static retrieveContextInfo(contextName: string, contextValue: T) { + const throttledService = ContextThrottleService.getInstance(); + const { prevValue, throttledValue } = throttledService.getContextThrottleInfoByName( + contextName, + contextValue, + ); + + return { prevValue, throttledValue }; + } + public static updateThrottledServiceSettings(settings: ContextThrottleServiceSettings) { const throttledService = ContextThrottleService.getInstance(); throttledService.interval = settings.interval; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index a8844d2..1cfbb1a 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -18,6 +18,17 @@ export const isPageObject = (path: NavigationTarget): path is Page | PageWithPar return typeof path === 'object' && 'path' in path; }; +export const areKeysEqual = (obj1: T, obj2: U): boolean => { + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + + if (keys1.length !== keys2.length) { + return false; + } + + return keys1.every((key) => keys2.includes(key)); +}; + export const isPageWithOptionsPath = ( path: NavigationTarget, ): path is Partial | ExtendedPathWithParams | ExtendedPath => {