From ac30fac7fe1fbcb76aa9f68b12a8a8e196add94f Mon Sep 17 00:00:00 2001 From: 0age <37939117+0age@users.noreply.github.com> Date: Tue, 10 Dec 2024 22:45:28 -0800 Subject: [PATCH] solve the rerendering fiasco --- frontend/src/App.tsx | 4 +- frontend/src/components/BalanceDisplay.tsx | 410 ++++++++++-------- .../src/components/FinalizationThreshold.tsx | 4 +- frontend/src/components/HealthCheck.tsx | 4 +- .../src/components/WithdrawalCountdown.tsx | 64 +-- frontend/src/context/NotificationProvider.tsx | 87 ++-- frontend/src/hooks/useBalanceDisplay.ts | 182 ++++---- frontend/src/hooks/useBalances.ts | 6 +- frontend/src/hooks/useCompact.ts | 2 +- frontend/src/hooks/useGraphQL.ts | 8 +- frontend/src/hooks/useResourceLocks.ts | 6 +- 11 files changed, 408 insertions(+), 369 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a1d6ea7..4f35e75 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -94,9 +94,7 @@ function AppContent() {
{/* Health Check Status */}
- +
{/* Only show these components if the server is healthy */} diff --git a/frontend/src/components/BalanceDisplay.tsx b/frontend/src/components/BalanceDisplay.tsx index d8bc3ac..76ab93e 100644 --- a/frontend/src/components/BalanceDisplay.tsx +++ b/frontend/src/components/BalanceDisplay.tsx @@ -12,10 +12,12 @@ import { formatLockId, getChainName, } from '../hooks/useBalanceDisplay'; +import type { Balance } from '../hooks/useBalances'; +import type { ResourceLockBalance } from '../hooks/useResourceLocks'; interface BalanceItemProps { - balance: any; - resourceLock: any; + balance: Balance; + resourceLock: ResourceLockBalance | undefined; onInitiateWithdrawal: (lockId: string) => void; onDisableWithdrawal: (chainId: string, lockId: string) => void; onExecuteWithdrawal: ( @@ -30,30 +32,38 @@ interface BalanceItemProps { } // Memoized balance value component -const BalanceValue = memo(function BalanceValue({ - balance, - decimals -}: { - balance: string, - decimals: number -}) { - const formattedValue = useMemo(() => { - return formatUnits(BigInt(balance), decimals); - }, [balance, decimals]); +const BalanceValue = memo( + function BalanceValue({ + balance, + decimals, + }: { + balance: string; + decimals: number; + }) { + const formattedValue = useMemo(() => { + return formatUnits(BigInt(balance), decimals); + }, [balance, decimals]); - return formattedValue; -}, (prev, next) => prev.balance === next.balance && prev.decimals === next.decimals); + return formattedValue; + }, + (prev, next) => + prev.balance === next.balance && prev.decimals === next.decimals +); // Helper function to compare resourceLock objects -const areResourceLocksEqual = (prev: any, next: any) => { +const areResourceLocksEqual = ( + prev: ResourceLockBalance | undefined, + next: ResourceLockBalance | undefined +) => { if (!prev || !next) return prev === next; - + // Compare critical fields that affect rendering - const tokenEqual = + const tokenEqual = prev.resourceLock.token.name === next.resourceLock.token.name && prev.resourceLock.token.symbol === next.resourceLock.token.symbol && prev.resourceLock.token.decimals === next.resourceLock.token.decimals && - prev.resourceLock.token.tokenAddress === next.resourceLock.token.tokenAddress; + prev.resourceLock.token.tokenAddress === + next.resourceLock.token.tokenAddress; const resourceLockEqual = prev.balance === next.balance && @@ -61,137 +71,158 @@ const areResourceLocksEqual = (prev: any, next: any) => { prev.withdrawableAt === next.withdrawableAt && prev.resourceLock.resetPeriod === next.resourceLock.resetPeriod && prev.resourceLock.isMultichain === next.resourceLock.isMultichain && - prev.resourceLock.lockId === next.resourceLock.lockId && + prev.resourceLock.token.tokenAddress === + next.resourceLock.token.tokenAddress && prev.chainId === next.chainId; return tokenEqual && resourceLockEqual; }; -const BalanceItem = memo(function BalanceItem({ - balance, - resourceLock, - onInitiateWithdrawal, - onDisableWithdrawal, - onExecuteWithdrawal, - sessionToken, -}: BalanceItemProps) { - const withdrawableAt = parseInt(balance.withdrawableAt || '0'); - const canExecuteWithdrawal = useMemo(() => { - const currentTime = Math.floor(Date.now() / 1000); - return parseInt(balance.withdrawalStatus.toString()) !== 0 && withdrawableAt <= currentTime; - }, [balance.withdrawalStatus, withdrawableAt]); +const BalanceItem = memo( + function BalanceItem({ + balance, + resourceLock, + onInitiateWithdrawal, + onDisableWithdrawal, + onExecuteWithdrawal, + sessionToken, + }: BalanceItemProps) { + const withdrawableAt = parseInt(balance.withdrawableAt || '0'); + const canExecuteWithdrawal = useMemo(() => { + const currentTime = Math.floor(Date.now() / 1000); + return ( + parseInt(balance.withdrawalStatus.toString()) !== 0 && + withdrawableAt <= currentTime + ); + }, [balance.withdrawalStatus, withdrawableAt]); - // Memoize handlers - const handleForceWithdraw = useCallback(() => { - onInitiateWithdrawal(balance.lockId); - }, [balance.lockId, onInitiateWithdrawal]); + // Memoize handlers + const handleForceWithdraw = useCallback(() => { + onInitiateWithdrawal(balance.lockId); + }, [balance.lockId, onInitiateWithdrawal]); - const handleDisableForceWithdraw = useCallback(() => { - onDisableWithdrawal(balance.chainId, balance.lockId); - }, [balance.chainId, balance.lockId, onDisableWithdrawal]); + const handleDisableForceWithdraw = useCallback(() => { + onDisableWithdrawal(balance.chainId, balance.lockId); + }, [balance.chainId, balance.lockId, onDisableWithdrawal]); - const handleExecuteWithdrawal = useCallback(() => { - onExecuteWithdrawal( + const handleExecuteWithdrawal = useCallback(() => { + onExecuteWithdrawal( + balance.chainId, + balance.lockId, + resourceLock?.balance || '0', + balance.token?.name || 'Token', + balance.token?.decimals || 18, + balance.token?.symbol || '' + ); + }, [ balance.chainId, balance.lockId, - resourceLock?.balance || '0', - balance.token?.name || 'Token', - balance.token?.decimals || 18, - balance.token?.symbol || '' - ); - }, [ - balance.chainId, - balance.lockId, - balance.token?.decimals, - balance.token?.name, - balance.token?.symbol, - onExecuteWithdrawal, - resourceLock?.balance, - ]); + balance.token?.decimals, + balance.token?.name, + balance.token?.symbol, + onExecuteWithdrawal, + resourceLock?.balance, + ]); - return ( -
- {/* Header with Token Info and Chain Name */} -
-
- {balance.token?.name} ({balance.token?.symbol}) -
-
-
Chain: {getChainName(balance.chainId)}
-
- Lock ID:{' '} - {formatLockId(balance.lockId)} + return ( +
+ {/* Header with Token Info and Chain Name */} +
+
+ {balance.token?.name} ({balance.token?.symbol}) +
+
+
Chain: {getChainName(balance.chainId)}
+
+ Lock ID:{' '} + {formatLockId(balance.lockId)} +
-
- {/* Resource Lock Properties */} -
- {balance.resourceLock?.resetPeriod && - balance.resourceLock.resetPeriod > 0 && ( + {/* Resource Lock Properties */} +
+ {balance.resourceLock?.resetPeriod && + balance.resourceLock.resetPeriod > 0 && ( + + Reset Period:{' '} + {formatResetPeriod(balance.resourceLock.resetPeriod)} + + )} + + {balance.resourceLock?.isMultichain && ( - Reset Period: {formatResetPeriod(balance.resourceLock.resetPeriod)} + Multichain )} - - {balance.resourceLock?.isMultichain && ( - - Multichain - - )} - {balance.withdrawalStatus === 0 && ( - - Active - - )} - {balance.withdrawalStatus !== 0 && ( - - )} -
+ {balance.withdrawalStatus === 0 && ( + + Active + + )} + {balance.withdrawalStatus !== 0 && ( + + )} +
- {/* Balances Grid */} -
- {/* Left side - Current, Allocatable, and Allocated */} -
-
-
Current Balance
-
- {resourceLock && ( - - )} - {balance.token?.symbol && ( - - {balance.token.symbol} - - )} + {/* Balances Grid */} +
+ {/* Left side - Current, Allocatable, and Allocated */} +
+
+
Current Balance
+
+ {resourceLock && ( + + )} + {balance.token?.symbol && ( + + {balance.token.symbol} + + )} +
-
-
-
Finalized Balance
-
- {balance.formattedAllocatableBalance || - balance.allocatableBalance} - {balance.token?.symbol && ( - - {balance.token.symbol} - - )} +
+
Finalized Balance
+
+ {balance.formattedAllocatableBalance || + balance.allocatableBalance} + {balance.token?.symbol && ( + + {balance.token.symbol} + + )} +
+
+ +
+
Currently Allocated
+
+ {balance.formattedAllocatedBalance || balance.allocatedBalance} + {balance.token?.symbol && ( + + {balance.token.symbol} + + )} +
-
-
Currently Allocated
-
- {balance.formattedAllocatedBalance || balance.allocatedBalance} + {/* Right side - Emphasized available to allocate */} +
+
Available to Allocate
+
+ {balance.formattedAvailableBalance || + balance.balanceAvailableToAllocate} {balance.token?.symbol && ( - + {balance.token.symbol} )} @@ -199,76 +230,70 @@ const BalanceItem = memo(function BalanceItem({
- {/* Right side - Emphasized available to allocate */} -
-
Available to Allocate
-
- {balance.formattedAvailableBalance || - balance.balanceAvailableToAllocate} - {balance.token?.symbol && ( - - {balance.token.symbol} - - )} + {/* Transfer and Withdrawal Actions */} + {resourceLock && ( +
+
+ + {canExecuteWithdrawal && ( + + )} +
-
+ )}
+ ); + }, + (prevProps, nextProps) => { + // Enhanced comparison function for memo + const balanceEqual = + prevProps.balance.lockId === nextProps.balance.lockId && + prevProps.balance.chainId === nextProps.balance.chainId && + prevProps.balance.withdrawalStatus === + nextProps.balance.withdrawalStatus && + prevProps.balance.withdrawableAt === nextProps.balance.withdrawableAt && + prevProps.balance.formattedAllocatableBalance === + nextProps.balance.formattedAllocatableBalance && + prevProps.balance.formattedAllocatedBalance === + nextProps.balance.formattedAllocatedBalance && + prevProps.balance.formattedAvailableBalance === + nextProps.balance.formattedAvailableBalance; - {/* Transfer and Withdrawal Actions */} - {resourceLock && ( -
-
- - {canExecuteWithdrawal && ( - - )} -
-
- )} -
- ); -}, (prevProps, nextProps) => { - // Enhanced comparison function for memo - const balanceEqual = - prevProps.balance.lockId === nextProps.balance.lockId && - prevProps.balance.chainId === nextProps.balance.chainId && - prevProps.balance.withdrawalStatus === nextProps.balance.withdrawalStatus && - prevProps.balance.withdrawableAt === nextProps.balance.withdrawableAt && - prevProps.balance.formattedAllocatableBalance === nextProps.balance.formattedAllocatableBalance && - prevProps.balance.formattedAllocatedBalance === nextProps.balance.formattedAllocatedBalance && - prevProps.balance.formattedAvailableBalance === nextProps.balance.formattedAvailableBalance; - - // Use the helper function to deeply compare resourceLocks - const resourceLockEqual = areResourceLocksEqual(prevProps.resourceLock, nextProps.resourceLock); + // Use the helper function to deeply compare resourceLocks + const resourceLockEqual = areResourceLocksEqual( + prevProps.resourceLock, + nextProps.resourceLock + ); - return ( - balanceEqual && - resourceLockEqual && - prevProps.sessionToken === nextProps.sessionToken - ); -}); + return ( + balanceEqual && + resourceLockEqual && + prevProps.sessionToken === nextProps.sessionToken + ); + } +); export function BalanceDisplay({ sessionToken, @@ -370,7 +395,8 @@ export function BalanceDisplay({

- {localStorage.getItem(`session-${address}`) || 'No session found'} + {localStorage.getItem(`session-${address}`) || + 'No session found'}