I have a table generated to document the issues in the original code and compare them with the refactored code. Here is the updated component that fixed all the issues: WalletPage.tsx
| Issue | Original Code (Before) | Refactored Code (After) | Improvement |
|---|---|---|---|
| Undefined Variables | Used lhsPriority and leftPriority which were never declared, causing runtime crashes. |
Properly scoped variables priorityA and priorityB extracted directly from the items being compared. |
Bug Fix: Code now executes without throwing ReferenceError. |
| Inverted Filter Logic | if (balance.amount <= 0) return true; kept empty/negative balances and discarded positive ones. |
return priority > -99 && balance.amount > 0; correctly filters out empty balances and unsupported chains. |
Bug Fix: Displays correct data to the user. |
| Missing Sort Return | The sort function did not return 0 for items with equal priority, leading to unstable sorting. |
Added a fallback return 0; to ensure strict sorting contract compliance. |
Bug Fix: Stable and predictable array sorting across all browsers. |
| Redundant Dependency | prices was included in the useMemo dependency array but never actually used inside the block. |
Removed unused dependencies and integrated pricing calculation cleanly in one pass. | Performance: Prevents unnecessary re-computations when prices update but balances do not. |
| Inefficient Lookups | getPriority used an O(N) switch statement that was re-evaluated constantly. |
Replaced with a static O(1) HashMap (Record<string, number>) defined outside the component. |
Performance: Faster lookups and prevents recreating the function on every render. |
| Multiple Array Passes | Mapped over the sorted array to create formattedBalances, then mapped again to create React rows, dropping the formatted data. |
Consolidated .filter, .sort, and .map into a single useMemo pipeline that handles formatting and USD calculation. |
Performance: Reduced memory allocation and fewer iterations over the array. |
| Index as React Key | Used key={index} when rendering <WalletRow />, which causes UI bugs during reordering/filtering. |
Used key={balance.currency} to ensure stable DOM elements during state changes. |
Performance & UX: Optimized React reconciliation and prevents component state leakage. |
interface WalletBalance {
currency: string;
amount: number;
}
interface FormattedWalletBalance {
currency: string;
amount: number;
formatted: string;
}
interface Props extends BoxProps {
}
const WalletPage: React.FC<Props> = (props: Props) => {
const { children, ...rest } = props;
const balances = useWalletBalances();
const prices = usePrices();
const getPriority = (blockchain: any): number => {
switch (blockchain) {
case 'Osmosis':
return 100
case 'Ethereum':
return 50
case 'Arbitrum':
return 30
case 'Zilliqa':
return 20
case 'Neo':
return 20
default:
return -99
}
}
const sortedBalances = useMemo(() => {
return balances.filter((balance: WalletBalance) => {
const balancePriority = getPriority(balance.blockchain);
if (lhsPriority > -99) {
if (balance.amount <= 0) {
return true;
}
}
return false
}).sort((lhs: WalletBalance, rhs: WalletBalance) => {
const leftPriority = getPriority(lhs.blockchain);
const rightPriority = getPriority(rhs.blockchain);
if (leftPriority > rightPriority) {
return -1;
} else if (rightPriority > leftPriority) {
return 1;
}
});
}, [balances, prices]);
const formattedBalances = sortedBalances.map((balance: WalletBalance) => {
return {
...balance,
formatted: balance.amount.toFixed()
}
})
const rows = sortedBalances.map((balance: FormattedWalletBalance, index: number) => {
const usdValue = prices[balance.currency] * balance.amount;
return (
<WalletRow
className={classes.row}
key={index}
amount={balance.amount}
usdValue={usdValue}
formattedAmount={balance.formatted}
/>
)
})
return (
<div {...rest}>
{rows}
</div>
)
}// Problem 3 Fix: Define BLOCKCHAIN_PRIORITY as a HashMap for O(1) lookup instead of O(n) switch
const BLOCKCHAIN_PRIORITY: Record<string, number> = {
'Osmosis': 100,
'Ethereum': 50,
'Arbitrum': 30,
'Zilliqa': 20,
'Neo': 20
};
// Mock balances since we don't have a real wallet connection
const generateMockBalances = (coins: Coin[]) => {
return coins.map((c, i) => ({
currency: c.currency,
blockchain: c.blockchain,
amount: i % 3 === 0 ? 0 : Math.random() * 100 + 10 // Every 3rd coin is empty
}));
};
export const WalletPage: FC<WalletPageProps> = ({ coins }) => {
const [showComparison, setShowComparison] = useState(false);
// Create mock balances only once
const balances = useMemo(() => generateMockBalances(coins), [coins]);
// Problem 3 Fix: Single pass filter, sort, and map using useMemo
const processedBalances = useMemo(() => {
return balances
// 1. Filter: Fix inverted logic (amount > 0)
.filter(balance => {
const priority = BLOCKCHAIN_PRIORITY[balance.blockchain] ?? -99;
return priority > -99 && balance.amount > 0;
})
// 2. Sort: Fix missing return 0
.sort((a, b) => {
const priorityA = BLOCKCHAIN_PRIORITY[a.blockchain] ?? -99;
const priorityB = BLOCKCHAIN_PRIORITY[b.blockchain] ?? -99;
if (priorityA > priorityB) return -1;
if (priorityA < priorityB) return 1;
return 0;
})
// 3. Map to include formatted data + USD value (since we have coins array with prices)
.map(balance => {
const coinInfo = coins.find(c => c.currency === balance.currency);
const price = coinInfo ? coinInfo.price : 0;
const usdValue = price * balance.amount;
return {
...balance,
formatted: balance.amount.toFixed(4),
usdValue,
iconFilename: coinInfo?.iconFilename
};
});
}, [balances, coins]); // Removed 'prices' dependency as they are inside 'coins'
return (
<div className="max-w-4xl mx-auto pt-4">
<div className="flex justify-between items-end mb-6">
<div>
<h1 className="text-2xl font-bold text-white">Your Wallet</h1>
<p className="text-slate-400 text-sm">Refactored version of the Problem 3 component</p>
</div>
<button
onClick={() => setShowComparison(!showComparison)}
className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-cyan-400 rounded-lg text-sm font-medium border border-slate-700 transition-colors"
>
{showComparison ? 'View Wallet' : 'View Code Comparison'}
</button>
</div>
{showComparison ? (
<WalletComparison />
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{processedBalances.map((balance) => (
<div key={balance.currency} className="glass-card p-4 flex items-center justify-between hover:bg-white/10 transition-colors">
<div className="flex items-center gap-4">
{balance.iconFilename ? (
<img src={`/coins/${balance.iconFilename}`} alt={balance.currency} className="w-10 h-10 rounded-full" />
) : (
<div className="w-10 h-10 rounded-full bg-slate-800 flex items-center justify-center text-slate-400 font-bold">
{balance.currency[0]}
</div>
)}
<div>
<h3 className="text-lg font-bold text-white">{balance.currency}</h3>
<span className="text-[10px] px-2 py-0.5 rounded-full bg-slate-800 border border-slate-700 text-slate-400 uppercase">
{balance.blockchain}
</span>
</div>
</div>
<div className="text-right">
<div className="font-mono text-white font-medium">{balance.formatted}</div>
<div className="text-sm text-slate-400">${balance.usdValue.toFixed(2)}</div>
</div>
</div>
))}
{processedBalances.length === 0 && (
<div className="col-span-full p-8 text-center text-slate-500 border border-dashed border-slate-700 rounded-2xl">
No balances found matching priority criteria.
</div>
)}
</div>
)}
</div>
);
}