From 25c4ff970d8056ac988026afb24d1932b5c9d219 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Thu, 14 Dec 2023 16:09:33 +0800 Subject: [PATCH] Significantly reduce number of renders Signed-off-by: Egor Savkin --- package-lock.json | 14 ++++++++++ package.json | 3 ++- static/js/shop/Backlog.jsx | 18 +++++-------- static/js/shop/Cart.jsx | 14 +++++++--- static/js/shop/Crate.jsx | 13 +++++----- static/js/shop/CrateList.jsx | 21 ++++++++------- static/js/shop/CrateMode.jsx | 16 +++++++----- static/js/shop/CrateWarnings.jsx | 10 ++++++-- static/js/shop/FakePlaceholder.jsx | 3 +++ static/js/shop/ImportJSON.jsx | 19 ++++++++------ static/js/shop/Layout.jsx | 14 +++++----- static/js/shop/OrderForm.jsx | 32 ++++++++++------------- static/js/shop/OrderPanel.jsx | 4 +++ static/js/shop/OrderSummary.jsx | 41 ++++++++++++------------------ static/js/shop/ProductCartItem.jsx | 33 ++++++++++++++---------- static/js/shop/ProductItem.jsx | 14 ++++++---- static/js/shop/RFQFeedback.jsx | 13 ++++++---- static/js/shop/Resources.jsx | 3 +++ static/js/shop/Shop.jsx | 25 ++++++++++++++---- static/js/shop/ShowJSON.jsx | 15 ++++++----- 20 files changed, 190 insertions(+), 135 deletions(-) diff --git a/package-lock.json b/package-lock.json index b1e5e38c..4f17989e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@babel/preset-env": "^7.23.2", "@babel/preset-react": "^7.22.15", "@hello-pangea/dnd": "^16.3.0", + "@uidotdev/usehooks": "^2.4.1", "babel-loader": "^9.1.3", "babel-preset-minify": "^0.5.2", "bootstrap": "^5.3.0", @@ -2171,6 +2172,19 @@ "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==", "dev": true }, + "node_modules/@uidotdev/usehooks": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz", + "integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", diff --git a/package.json b/package.json index 3aa28660..7aa83be3 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "json-logic-js": "^2.0.2", - "zustand": "^4.4.7" + "zustand": "^4.4.7", + "@uidotdev/usehooks":"^2.4.1" }, "babel": { "presets": [ diff --git a/static/js/shop/Backlog.jsx b/static/js/shop/Backlog.jsx index 7bc440f9..7d1aff0a 100644 --- a/static/js/shop/Backlog.jsx +++ b/static/js/shop/Backlog.jsx @@ -2,24 +2,20 @@ import React from 'react'; import {Droppable} from "@hello-pangea/dnd"; import {ProductItem} from "./ProductItem"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that renders the backlog in the aside */ export function Backlog() { - const { - data, - items, - onClickToggleMobileSideMenu, - isMobile, - } = useShopStore(state=> ({ - data: state.groups, - items: state.cards, - onClickToggleMobileSideMenu: state.switchSideMenu, - isMobile: state.isMobile - })); + const renderCount = useRenderCount(); + const data = useShopStore((state) => state.groups); + const items = useShopStore((state) => state.cards); + const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu); + const isMobile = useShopStore((state) => state.isMobile); + console.log("Backlog renders: ", renderCount) const ordered_groups = data.categories.map(groupItem => ({ name: groupItem.name, items: groupItem.itemIds.map(itemId => items[itemId]) diff --git a/static/js/shop/Cart.jsx b/static/js/shop/Cart.jsx index 2baae648..7bf72b11 100644 --- a/static/js/shop/Cart.jsx +++ b/static/js/shop/Cart.jsx @@ -6,15 +6,21 @@ import {FakePlaceholder} from "./FakePlaceholder"; import {FillExtData} from "./options/utils"; import {hp_to_slots} from "./count_resources"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; +import {useShallow} from "zustand/react/shallow"; /** * Component that displays a list of */ export function Cart({crate_index}) { - const {crate, crateParams} = useShopStore(state => ({ - crate: state.crates[crate_index], - crateParams: state.crateParams - })); + const renderCount = useRenderCount(); + + const crate = useShopStore(useShallow((state) => state.crates[crate_index]), (a, b) => { + return a.items.length === b.items.length && a.occupiedHP === b.occupiedHP && a.crate_mode === b.crate_mode + }); + const crateParams = useShopStore((state) => state.crateParams); + + console.log("Cart renders: ", renderCount) const nbrOccupied = hp_to_slots(crate.occupiedHP); const nbrSlots = hp_to_slots(crateParams(crate.crate_mode).hp); diff --git a/static/js/shop/Crate.jsx b/static/js/shop/Crate.jsx index b59ca3ee..4e4d50b6 100644 --- a/static/js/shop/Crate.jsx +++ b/static/js/shop/Crate.jsx @@ -3,20 +3,19 @@ import {Cart} from "./Cart"; import {CrateMode} from "./CrateMode"; import {CrateWarnings} from "./CrateWarnings"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that displays the main crate with reminder rules. * It includes and rules */ export function Crate({crate_index}) { - const { - onDeleteCrate, - crate - } = useShopStore(state => ({ - onDeleteCrate: state.delCrate, - crate: state.crates[crate_index] - })) + const renderCount = useRenderCount(); + const crate = useShopStore((state) => state.crates[crate_index], + (a, b) => a.length === b.length); + const onDeleteCrate = useShopStore((state) => state.delCrate); + console.log("Crate renders: ", renderCount) return (
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx index b1c8a0a0..4819a56e 100644 --- a/static/js/shop/CrateList.jsx +++ b/static/js/shop/CrateList.jsx @@ -2,19 +2,18 @@ import React from 'react' import {Accordion} from "react-bootstrap"; import {Crate} from "./Crate"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; export function CrateList() { - const { - crates, - active_crate, - onAddCrate, - setActiveCrate, - } = useShopStore(state=> ({ - crates: state.crates, - active_crate: state.active_crate, - onAddCrate: state.newCrate, - setActiveCrate: state.setActiveCrate, - })); + const renderCount = useRenderCount(); + + const crates = useShopStore((state) => state.crates, + (a, b) => a.length === b.length); + const active_crate = useShopStore((state) => state.active_crate); + const onAddCrate = useShopStore((state) => state.newCrate); + const setActiveCrate = useShopStore((state) => state.setActiveCrate); + + console.log("CrateList renders: ", renderCount) return ( { // if e === null, that means that an accordion item was collapsed rather than expanded. e will be non-null when an item is expanded diff --git a/static/js/shop/CrateMode.jsx b/static/js/shop/CrateMode.jsx index 8478a822..16d25d1b 100644 --- a/static/js/shop/CrateMode.jsx +++ b/static/js/shop/CrateMode.jsx @@ -1,16 +1,20 @@ import React from 'react'; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that displays crate modes */ export function CrateMode({crate_index}) { - const {modes_order, crate_modes, crate, setMode} = useShopStore(state => ({ - modes_order: state.modes_order, - crate_modes: state.crate_modes, - crate: state.crates[crate_index], - setMode: state.setCrateMode - })) + const renderCount = useRenderCount(); + + const modes_order = useShopStore((state) => state.modes_order); + const crate_modes = useShopStore((state) => state.crate_modes); + const crate = useShopStore((state) => state.crates[crate_index], + (a, b) => a.id === b.id && a.crate_mode === b.crate_mode); + const setMode = useShopStore((state) => state.setCrateMode); + + console.log("CrateMode renders: ", renderCount) return (
{modes_order.map((mode_name, _) => ( diff --git a/static/js/shop/CrateWarnings.jsx b/static/js/shop/CrateWarnings.jsx index 8c266319..29a14bda 100644 --- a/static/js/shop/CrateWarnings.jsx +++ b/static/js/shop/CrateWarnings.jsx @@ -1,10 +1,16 @@ import React from "react"; import {LevelUI} from "./warnings"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; + +const compareArrays = (a, b) => + a.length === b.length && + a.every((element, index) => element.id === b[index].id); export function CrateWarnings({crate_index}) { - const crate = useShopStore(state => (state.crates[crate_index])) - const crate_warnings = crate.warnings; + const renderCount = useRenderCount(); + const crate_warnings = useShopStore(state => (state.crates[crate_index].warnings), compareArrays) + console.log("CrateWarnings renders: ", renderCount) // TODO UI/colors return (
diff --git a/static/js/shop/FakePlaceholder.jsx b/static/js/shop/FakePlaceholder.jsx index 00f1a34e..8b0edafe 100644 --- a/static/js/shop/FakePlaceholder.jsx +++ b/static/js/shop/FakePlaceholder.jsx @@ -1,10 +1,12 @@ import React from 'react'; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that displays a placeholder inside crate. * Allows to display how it remains space for the current crate. */ export function FakePlaceholder({isDraggingOver, nToDraw}) { + const renderCount = useRenderCount(); const fakePlaceholder = []; for (let i = nToDraw; i > 0; i--) { @@ -17,6 +19,7 @@ export function FakePlaceholder({isDraggingOver, nToDraw}) { }}>
); } + //console.log("FakePlaceholder renders: ", renderCount) return ( diff --git a/static/js/shop/ImportJSON.jsx b/static/js/shop/ImportJSON.jsx index ace715e5..0a1fde0e 100644 --- a/static/js/shop/ImportJSON.jsx +++ b/static/js/shop/ImportJSON.jsx @@ -3,6 +3,7 @@ import {useClickAway} from "./options/useClickAway"; import {Modal} from "react-bootstrap"; import React from "react"; import {Validation} from "./validate"; +import {useRenderCount} from "@uidotdev/usehooks"; const JSONExample = JSON.stringify({ "items": [{"pn": "1124"}, {"pn": "2118"}, {"pn": "2118"}, {"pn": "2128"}], @@ -10,14 +11,16 @@ const JSONExample = JSON.stringify({ }); export function ImportJSON() { - const {shouldShow, data, loadDescription, updateImportDescription, closeImport, showImport} = useShopStore(state => ({ - shouldShow: state.importShouldOpen, - data: state.importValue, - loadDescription: state.loadDescription, - updateImportDescription: state.updateImportDescription, - closeImport: state.closeImport, - showImport: state.openImport, - })); + const renderCount = useRenderCount(); + + const shouldShow = useShopStore((state) => state.importShouldOpen); + const data = useShopStore((state) => state.importValue); + const loadDescription = useShopStore((state) => state.loadDescription); + const updateImportDescription = useShopStore((state) => state.updateImportDescription); + const closeImport = useShopStore((state) => state.closeImport); + const showImport = useShopStore((state) => state.openImport); + + console.log("ImportJSON renders: ", renderCount) const ref = useClickAway((e) => { if (e.type === "mousedown") // ignore touchstart diff --git a/static/js/shop/Layout.jsx b/static/js/shop/Layout.jsx index 517a4e18..9863cd98 100644 --- a/static/js/shop/Layout.jsx +++ b/static/js/shop/Layout.jsx @@ -1,5 +1,6 @@ import React from 'react'; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that provides a base layout (aside/main) for the page. @@ -7,12 +8,13 @@ import {useShopStore} from "./shop_store"; export function Layout({aside, main}) { - const {mobileSideMenuShouldOpen, onClickToggleMobileSideMenu, showCardAddedFeedback} = useShopStore((state) => ({ - mobileSideMenuShouldOpen: state.sideMenuIsOpen, - onClickToggleMobileSideMenu: state.switchSideMenu, - showCardAddedFeedback: state.showCardAddedFeedback, - isMobile: state.isMobile, - })); + const renderCount = useRenderCount(); + + const mobileSideMenuShouldOpen = useShopStore(state => state.sideMenuIsOpen); + const onClickToggleMobileSideMenu = useShopStore(state => state.switchSideMenu); + const showCardAddedFeedback = useShopStore(state => state.showCardAddedFeedback); + + console.log("Layout renders: ", renderCount) return (
diff --git a/static/js/shop/OrderForm.jsx b/static/js/shop/OrderForm.jsx index a5f83635..f3863692 100644 --- a/static/js/shop/OrderForm.jsx +++ b/static/js/shop/OrderForm.jsx @@ -2,31 +2,25 @@ import React from 'react' import {Validation} from "./validate.js"; import {useShopStore} from "./shop_store"; import {ShowJSON} from "./ShowJSON"; +import {useRenderCount} from "@uidotdev/usehooks"; + /** * Components that renders the form to request quote. */ export function OrderForm() { - const { - email, - note, - isProcessing, - updateEmail, - updateNote, - resetEmailValidation, - submitForm, - submitDisabled, - } = useShopStore(state => ({ - email: state.email, - note: state.note, - isProcessing: state.isProcessing, - updateEmail: state.updateEmail, - updateNote: state.updateNote, - submitForm: state.submitForm, - submitDisabled: state.submitDisabled, - resetEmailValidation: state.resetEmailValidation - })); + const renderCount = useRenderCount(); + const email = useShopStore((state) => state.email); + const note = useShopStore((state) => state.note); + const isProcessing = useShopStore((state) => state.isProcessing); + const updateEmail = useShopStore((state) => state.updateEmail); + const updateNote = useShopStore((state) => state.updateNote); + const submitForm = useShopStore((state) => state.submitForm); + const submitDisabled = useShopStore((state) => state.submitDisabled); + const resetEmailValidation = useShopStore((state) => state.resetEmailValidation); + + console.log("OrderForm renders: ", renderCount) return (
diff --git a/static/js/shop/OrderPanel.jsx b/static/js/shop/OrderPanel.jsx index 55b5e505..881c34e4 100644 --- a/static/js/shop/OrderPanel.jsx +++ b/static/js/shop/OrderPanel.jsx @@ -5,15 +5,19 @@ import {CrateList} from "./CrateList"; import {useShopStore} from "./shop_store"; import {ImportJSON} from "./ImportJSON"; import {RFQFeedback} from "./RFQFeedback"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that renders all things for order. * It acts like-a layout, this component do nothing more. */ export function OrderPanel({title, description}) { + const renderCount = useRenderCount(); const isMobile = useShopStore((state) => state.isMobile); const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu); + console.log("OrderPanel renders: ", renderCount) + return (

{title}

diff --git a/static/js/shop/OrderSummary.jsx b/static/js/shop/OrderSummary.jsx index 1526e78a..6fa03502 100644 --- a/static/js/shop/OrderSummary.jsx +++ b/static/js/shop/OrderSummary.jsx @@ -3,38 +3,29 @@ import {SummaryPopup} from "./options/SummaryPopup"; import {formatMoney} from "./utils"; import {WarningIndicator} from "./CardWarnings"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Components that displays the list of card that are used in the crate. * It is a summary of purchase */ export function OrderSummary() { + const renderCount = useRenderCount(); - const { - currency, - crates, - total_price, - crateParams, - deleteCard, - setHighlight, - resetHighlight, - highlighted, - clearCrate, - delCrate, - clearAll - } = useShopStore(state =>({ - currency: state.currency, - crates: state.crates, - total_price: state.totalOrderPrice(), - crateParams: state.crateParams, - deleteCard: state.deleteCard, - setHighlight: state.highlightCard, - resetHighlight: state.highlightReset, - highlighted: state.highlighted, - clearAll: state.clearAll, - clearCrate: state.clearCrate, - delCrate: state.delCrate, - })); + const currency = useShopStore((state) => state.currency); + const crates = useShopStore((state) => state.crates); + const total_price = useShopStore((state) => state.totalOrderPrice()); + const crateParams = useShopStore((state) => state.crateParams); + const deleteCard = useShopStore((state) => state.deleteCard); + const setHighlight = useShopStore((state) => state.highlightCard); + const resetHighlight = useShopStore((state) => state.highlightReset); + const highlighted = useShopStore((state) => state.highlighted); + const clearAll = useShopStore((state) => state.clearAll); + const clearCrate = useShopStore((state) => state.clearCrate); + const delCrate = useShopStore((state) => state.delCrate); + + + console.log("OrderSummary renders: ", renderCount) return (
diff --git a/static/js/shop/ProductCartItem.jsx b/static/js/shop/ProductCartItem.jsx index 6849404f..cce5e72b 100644 --- a/static/js/shop/ProductCartItem.jsx +++ b/static/js/shop/ProductCartItem.jsx @@ -5,21 +5,26 @@ import {productStyle} from "./utils"; import {Resources} from "./Resources"; import {CardWarnings} from "./CardWarnings"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that renders a product. * Used in the crate */ export function ProductCartItem({card_index, crate_index, ext_data, first, last}) { - const {card, crate, highlighted, setHighlight, removeHighlight, onCardUpdate, onCardRemove} = useShopStore(state => ({ - card: state.crates[crate_index].items[card_index], - highlighted: state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card, - crate: state.crates[crate_index], - setHighlight: state.highlightCard, - removeHighlight: state.highlightReset, - onCardUpdate: state.updateOptions, - onCardRemove: state.deleteCard - })) + const renderCount = useRenderCount(); + + + const card = useShopStore((state) => state.crates[crate_index].items[card_index], + (a, b) => a.id === b.id && a.show_warnings === b.show_warnings && a.counted_resources === b.counted_resources ); + const highlighted = useShopStore((state) => state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card); + const crate_id = useShopStore((state) => state.crates[crate_index].id); + const setHighlight = useShopStore((state) => state.highlightCard); + const removeHighlight = useShopStore((state) => state.highlightReset); + const onCardUpdate = useShopStore((state) => state.updateOptions); + const onCardRemove = useShopStore((state) => state.deleteCard); + + console.log("ProductCartItem renders: ", renderCount) let options, options_data; const warnings = card && card.show_warnings; @@ -50,7 +55,7 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last} true ) }} - onMouseEnter={() => setHighlight(crate.id, card_index)} + onMouseEnter={() => setHighlight(crate_id, card_index)} onMouseLeave={removeHighlight} > @@ -79,7 +84,7 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last} update: ((outvar, value) => { // console.log("update", outvar, value, options_data); if (outvar in options_data) options_data[outvar] = value; - onCardUpdate(crate.id, card_index, {[outvar]: value}); + onCardUpdate(crate_id, card_index, {[outvar]: value}); }) }} /> @@ -89,8 +94,8 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last}
{card.name_number}
setHighlight(crate.id, card_index)} - onClick={() => setHighlight(crate.id, card_index)} + onMouseEnter={() => setHighlight(crate_id, card_index)} + onClick={() => setHighlight(crate_id, card_index)} > onCardRemove(crate.id, card_index)}> + onClick={() => onCardRemove(crate_id, card_index)}> rm diff --git a/static/js/shop/ProductItem.jsx b/static/js/shop/ProductItem.jsx index bbf7164b..3a0d4957 100644 --- a/static/js/shop/ProductItem.jsx +++ b/static/js/shop/ProductItem.jsx @@ -2,17 +2,21 @@ import React from 'react'; import {Draggable} from "@hello-pangea/dnd"; import {formatMoney, productStyle} from "./utils"; import {useShopStore} from "./shop_store"; +import {useRenderCount} from "@uidotdev/usehooks"; /** * Component that renders a product. * Used in the aside (e.g backlog of product) */ export function ProductItem({card_index}) { - const {card, currency, onAddCard} = useShopStore(state => ({ - card: state.getCardDescription(card_index), - currency: state.currency, - onAddCard: state.addCardFromBacklog - })); + const renderCount = useRenderCount(); + + const getCardDescription = useShopStore((state) => state.getCardDescription); + const currency = useShopStore((state) => state.currency); + const onAddCard = useShopStore((state) => state.addCardFromBacklog); + const card = getCardDescription(card_index); + + console.log("ProductItem renders: ", renderCount) const render_specs = (card.specs && card.specs.length > 0 && ( diff --git a/static/js/shop/RFQFeedback.jsx b/static/js/shop/RFQFeedback.jsx index 03e48d9d..28ba2638 100644 --- a/static/js/shop/RFQFeedback.jsx +++ b/static/js/shop/RFQFeedback.jsx @@ -3,13 +3,16 @@ import {useClickAway} from "./options/useClickAway"; import {Modal} from "react-bootstrap"; import {Validation} from "./validate"; import React from "react"; +import {useRenderCount} from "@uidotdev/usehooks"; export function RFQFeedback() { - const {closeRFQ, shouldShow, status} = useShopStore(state => ({ - closeRFQ: state.closeRFQFeedback, - shouldShow: state.shouldShowRFQFeedback, - status: state.processingResult - })) + const renderCount = useRenderCount(); + + const closeRFQ = useShopStore((state) => state.closeRFQFeedback); + const shouldShow = useShopStore((state) => state.shouldShowRFQFeedback); + const status = useShopStore((state) => state.processingResult); + + console.log("RFQFeedback renders: ", renderCount) const ref = useClickAway((e) => { if (e.type === "mousedown") // ignore touchstart diff --git a/static/js/shop/Resources.jsx b/static/js/shop/Resources.jsx index 34b0cf03..a074277f 100644 --- a/static/js/shop/Resources.jsx +++ b/static/js/shop/Resources.jsx @@ -1,6 +1,7 @@ import {OverlayTrigger} from "react-bootstrap"; import React from "react"; import {v4 as uuidv4} from "uuid"; +import {useRenderCount} from "@uidotdev/usehooks"; const resourcesWidthStyle = (occupied, max) => { @@ -62,6 +63,8 @@ function RenderResources({resources, library}) { } export function Resources({resources}) { + const renderCount = useRenderCount(); + console.log("Resources renders: ", renderCount) return ( ({ + const renderCount = useRenderCount(); + + const addCardFromBacklog = useShopStore((state) => state.addCardFromBacklog); + const moveCard = useShopStore((state) => state.moveCard); + const deleteCard = useShopStore((state) => state.deleteCard); + const cardIndexById = useShopStore((state) => state.cardIndexById); + + /*const {addCardFromBacklog, moveCard, deleteCard, cardIndexById} = useShopStore(useShallow(state => ({ addCardFromBacklog: state.addCardFromBacklog, moveCard: state.moveCard, deleteCard: state.deleteCard, cardIndexById: state.cardIndexById - })); + })));*/ const handleOnDragEnd = (drop_result, _provided) => { if (!drop_result.destination) { console.warn("No drop destination"); @@ -25,7 +33,7 @@ export function Shop() { } if (drop_result.source.droppableId === "backlog") addCardFromBacklog(drop_result.destination.droppableId, drop_result.source.index, drop_result.destination.index); - else if(drop_result.destination.droppableId === "backlog") + else if (drop_result.destination.droppableId === "backlog") deleteCard(drop_result.destination.droppableId, drop_result.destination.index); else moveCard(drop_result.source.droppableId, drop_result.source.index, drop_result.destination.droppableId, drop_result.destination.index) @@ -35,6 +43,7 @@ export function Shop() { addCardFromBacklog(null, [cardIndexById("eem_pwr_mod"), cardIndexById("kasli")], -1, true); }, []); + console.log("Shop renders: ", renderCount) return ( Drag and drop the cards you want into the crate below to see how the combination would look like. Setup card's configuration by tapping at the top of the card, most of the options can be modified after shipment. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at sales@m-labs.hk. The price is estimated and must be confirmed by a quote.

)} - /> + description={( +

Drag and drop the cards you want into the crate below to see how + the combination would look like. Setup card's configuration by tapping at the top of the + card, most of the options can be modified after shipment. If you have any issues with + this ordering system, or if you need other configurations, email us directly anytime + at sales@m-labs.hk. The price is estimated and must + be confirmed by a quote.

)} + /> )}>
diff --git a/static/js/shop/ShowJSON.jsx b/static/js/shop/ShowJSON.jsx index 84987a99..b5e987c8 100644 --- a/static/js/shop/ShowJSON.jsx +++ b/static/js/shop/ShowJSON.jsx @@ -2,14 +2,17 @@ import React from "react"; import {Modal} from "react-bootstrap"; import {useShopStore} from "./shop_store"; import {useClickAway} from "./options/useClickAway"; +import {useRenderCount} from "@uidotdev/usehooks"; export function ShowJSON() { - const {shouldShow, description, showDescription, closeDescription} = useShopStore(state => ({ - shouldShow: state.shouldShowDescription, - description: state.description, - closeDescription: state.closeDescription, - showDescription: state.showDescription, - })); + const renderCount = useRenderCount(); + + const shouldShow = useShopStore((state) => state.shouldShowDescription); + const description = useShopStore((state) => state.description); + const closeDescription = useShopStore((state) => state.closeDescription); + const showDescription = useShopStore((state) => state.showDescription); + + console.log("ShowJSON renders: ", renderCount) const ref = useClickAway((e) => { if (e.type === "mousedown") // ignore touchstart