diff --git a/src/app/WardrobePage/Item.js b/src/app/WardrobePage/Item.js
index 4289cfe..64b2b67 100644
--- a/src/app/WardrobePage/Item.js
+++ b/src/app/WardrobePage/Item.js
@@ -86,7 +86,7 @@ function Item({
icon={}
label="Remove"
onClick={(e) => {
- onRemove();
+ onRemove(item.id);
e.preventDefault();
}}
/>
diff --git a/src/app/WardrobePage/ItemsPanel.js b/src/app/WardrobePage/ItemsPanel.js
index 3a1c265..488e528 100644
--- a/src/app/WardrobePage/ItemsPanel.js
+++ b/src/app/WardrobePage/ItemsPanel.js
@@ -117,6 +117,13 @@ function ItemZoneGroup({
}
};
+ const onRemove = React.useCallback(
+ (itemId) => {
+ dispatchToOutfit({ type: "removeItem", itemId });
+ },
+ [dispatchToOutfit]
+ );
+
return (
@@ -136,9 +143,7 @@ function ItemZoneGroup({
!isDisabled && outfitState.wornItemIds.includes(item.id)
}
isInOutfit={outfitState.allItemIds.includes(item.id)}
- onRemove={() =>
- dispatchToOutfit({ type: "removeItem", itemId: item.id })
- }
+ onRemove={onRemove}
isDisabled={isDisabled}
/>
);
diff --git a/src/app/WardrobePage/useOutfitState.js b/src/app/WardrobePage/useOutfitState.js
index ab56616..3a6b196 100644
--- a/src/app/WardrobePage/useOutfitState.js
+++ b/src/app/WardrobePage/useOutfitState.js
@@ -72,7 +72,39 @@ function useOutfitState() {
}
);
- const items = data?.items || [];
+ const resultItems = data?.items || [];
+
+ // Okay, time for some big perf hacks! Lower down in the app, we use
+ // React.memo to avoid re-rendering Item components if the items haven't
+ // updated. In simpler cases, we just make the component take the individual
+ // item fields as props... but items are complex and that makes it annoying
+ // :p Instead, we do these tricks to reuse physical item objects if they're
+ // still deep-equal to the previous version. This is because React.memo uses
+ // object identity to compare its props, so now when it checks whether
+ // `oldItem === newItem`, the answer will be `true`, unless the item really
+ // _did_ change!
+ const [cachedItemObjects, setCachedItemObjects] = React.useState([]);
+ let items = resultItems.map((item) => {
+ const cachedItemObject = cachedItemObjects.find((i) => i.id === item.id);
+ if (
+ cachedItemObject &&
+ JSON.stringify(cachedItemObject) === JSON.stringify(item)
+ ) {
+ return cachedItemObject;
+ }
+ return item;
+ });
+ if (
+ items.length === cachedItemObjects.length &&
+ items.every((_, index) => items[index] === cachedItemObjects[index])
+ ) {
+ // Even reuse the entire array if none of the items changed!
+ items = cachedItemObjects;
+ }
+ React.useEffect(() => {
+ setCachedItemObjects(items);
+ }, [items, setCachedItemObjects]);
+
const itemsById = {};
for (const item of items) {
itemsById[item.id] = item;