optimization
Virtualization for the card list -> Faster loading when searching
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import React, { useContext, useState, memo } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { CardContext } from '../../store/CardContext';
|
||||
|
||||
function PrintingRow({ card_id, printing }) {
|
||||
const { ownedAmounts, updateAmount } = useContext(CardContext);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const currentAmount = ownedAmounts[card_id]?.[printing.set_id]?.[printing.rarity_id] ?? printing.amount_owned ?? 0;
|
||||
// Combined key for uniqueness
|
||||
const key = `${printing.set_id}-${printing.rarity_id}`;
|
||||
const currentAmount = ownedAmounts[card_id]?.[key] ?? printing.amount_owned ?? 0;
|
||||
|
||||
const updateBackend = async (newAmount) => {
|
||||
const { set_id, rarity_id } = printing;
|
||||
@@ -16,22 +18,39 @@ function PrintingRow({ card_id, printing }) {
|
||||
const response = await fetch('http://localhost:3000/collection/amount', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ card_id, set_id, rarity_id, amount_owned: newAmount })
|
||||
body: JSON.stringify({
|
||||
card_id,
|
||||
set_id,
|
||||
rarity_id,
|
||||
amount_owned: newAmount
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
updateAmount(card_id, set_id, rarity_id, newAmount);
|
||||
// Update context using the combined key
|
||||
updateAmount(card_id, key, newAmount);
|
||||
}
|
||||
} catch (err) {
|
||||
// silently fail
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const increment = () => updateBackend(currentAmount + 1);
|
||||
const decrement = () => { if (currentAmount > 0) updateBackend(currentAmount - 1); };
|
||||
const decrement = () => {
|
||||
if (currentAmount > 0) updateBackend(currentAmount - 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '0.25rem 0', opacity: loading ? 0.6 : 1 }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
padding: '0.25rem 0',
|
||||
opacity: loading ? 0.6 : 1
|
||||
}}
|
||||
>
|
||||
<span>{printing.set_name} {printing.rarity_name}</span>
|
||||
<div>
|
||||
<button onClick={decrement} disabled={loading || currentAmount === 0}>–</button>
|
||||
@@ -42,4 +61,21 @@ function PrintingRow({ card_id, printing }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(PrintingRow);
|
||||
// ✅ Memoize PrintingRow for performance
|
||||
export default React.memo(
|
||||
PrintingRow,
|
||||
(prevProps, nextProps) => {
|
||||
// Re-render only if card_id changes or printing reference changes
|
||||
// or if the current amount changed
|
||||
const prevKey = `${prevProps.printing.set_id}-${prevProps.printing.rarity_id}`;
|
||||
const nextKey = `${nextProps.printing.set_id}-${nextProps.printing.rarity_id}`;
|
||||
const prevAmount = prevProps.printing.amount_owned;
|
||||
const nextAmount = nextProps.printing.amount_owned;
|
||||
|
||||
return (
|
||||
prevProps.card_id === nextProps.card_id &&
|
||||
prevKey === nextKey &&
|
||||
prevAmount === nextAmount
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState, useContext } from 'react';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import CardRow from '../components/CardRow/CardRow';
|
||||
import SearchBar from '../components/SearchBar/SearchBar';
|
||||
import { fetchCards } from '../services/api';
|
||||
@@ -59,12 +60,16 @@ function HomePage() {
|
||||
return (
|
||||
<div style={{ display: 'flex', height: '100vh' }}>
|
||||
{/* Left panel: card list */}
|
||||
<div style={{ flex: 2, borderRight: '1px solid #ccc', padding: '1rem', overflowY: 'auto' }}>
|
||||
<div style={{ flex: 2, borderRight: '1px solid #ccc', padding: '1rem' }}>
|
||||
<h2>Card List</h2>
|
||||
<SearchBar searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
|
||||
{filteredCards.map(card => (
|
||||
<CardRow key={card.id} card={card} />
|
||||
))}
|
||||
|
||||
{/* ✅ Virtualized list */}
|
||||
<Virtuoso
|
||||
style={{ height: 'calc(100vh - 100px)' }} // Adjust for header/search bar
|
||||
data={filteredCards}
|
||||
itemContent={(index, card) => <CardRow key={card.id} card={card} />}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Right panel: card image */}
|
||||
|
||||
Reference in New Issue
Block a user