我遇到了性能问题。我不确定是否是因为我使用了多个useEffect(我试图通过让他们观看相关状态来限制他们的行为)?
或者也许是因为我使用了一堆if语句?还是我正在执行的所有过滤器?
目标是使用户能够检查和取消检查不同的功能,并计算得出的价格。计算的价格会根据所选的选项(年度/订阅)而有所不同。
您可以在这里看到问题:https://prisma2-frontend-project.now.sh/
如果您向下滚动到“定价”部分,则可以看到,如果您开始选择和取消选择一个或两个复选框,那实际上不是问题。但是,当您开始做更多事情或切换到“购买”标签时,事情开始真正陷入困境。数学甚至开始变得奇怪!哈哈
相关代码:
import React, { useState, useEffect, useRef } from "react";
import PropTypes from "prop-types";
import Link from "next/link";
import Box from "reusecore/src/elements/Box";
import Text from "reusecore/src/elements/Text";
import Heading from "reusecore/src/elements/Heading";
import Checkbox from "reusecore/src/elements/Checkbox";
import Button from "reusecore/src/elements/Button";
import Container from "common/src/components/UI/Container";
import GlideCarousel from "common/src/components/GlideCarousel";
import GlideSlide from "common/src/components/GlideCarousel/glideSlide";
import { useToggle } from "reusecore/src/hooks";
import {
MONTHLY_PRICING_TABLE,
YEARLY_PRICING_TABLE
} from "common/src/data/SaasClassic";
import PricingTable, {
PricingHead,
PricingPrice,
PricingButton,
PricingList,
ListItem,
PricingButtonWrapper,
PricingTableWrapper
} from "./pricing.style";
const PricingSection = ({
sectionWrapper,
isChecked,
secTitleWrapper,
secHeading,
secText,
nameStyle,
descriptionStyle,
priceStyle,
priceLabelStyle,
buttonFillStyle,
listContentStyle
}) => {
const [state, setState] = useState({
data: MONTHLY_PRICING_TABLE,
active: true
});
const [loading, setLoading] = useState(false);
useEffect(() => {
const sumSubscriptionBusiness = businessState.subscription.cost.reduce(
(total, next) => total + Number(next),
0
);
const sumPurchaseBusiness = businessState.purchase.cost.reduce(
(total, next) => total + Number(next),
0
);
setBusinessTotal({
purchase: sumPurchaseBusiness,
subscription: sumSubscriptionBusiness
});
}, businessState);
useEffect(() => {
const sumSubscriptionInformation = informationState.subscription.cost.reduce(
(total, next) => total + Number(next),
0
);
const sumPurchaseInformation = informationState.purchase.cost.reduce(
(total, next) => total + Number(next),
0
);
setInformationTotal({
purchase: sumPurchaseInformation,
subscription: sumSubscriptionInformation
});
}, informationState);
useEffect(() => {
const sumSubscriptionEcommerce = ecommerceState.subscription.cost.reduce(
(total, next) => total + Number(next),
0
);
const sumPurchaseEcommerce = ecommerceState.purchase.cost.reduce(
(total, next) => total + Number(next),
0
);
setEcommerceTotal({
purchase: sumPurchaseEcommerce,
subscription: sumSubscriptionEcommerce
});
}, ecommerceState);
const [toggleValue, toggleHandler] = useToggle(isChecked);
const [businessState, setBusinessState] = useState({
purchase: {
service: [],
cost: []
},
subscription: {
service: [],
cost: []
}
});
const [informationState, setInformationState] = useState({
purchase: {
service: [],
cost: []
},
subscription: {
service: [],
cost: []
}
});
const [ecommerceState, setEcommerceState] = useState({
purchase: {
service: [],
cost: []
},
subscription: {
service: [],
cost: []
}
});
const [businessTotal, setBusinessTotal] = useState({
purchase: [],
subscription: []
});
const [informationTotal, setInformationTotal] = useState({
purchase: [],
subscription: []
});
const [ecommerceTotal, setEcommerceTotal] = useState({
purchase: [],
subscription: []
});
const handleChecking = (e, item) => {
const { name } = e.target;
const { id } = e.target;
const newService = item.service;
const newCost = item.cost;
const newPCost = item.pcost;
if (
name === "business" &&
businessState.subscription.service[0] !== undefined &&
!Object.values(businessState.subscription.service).includes(newService)
) {
const oldBusinessPurchaseService = businessState.purchase.service;
const oldBusinessPurchaseCost = businessState.purchase.cost;
const oldBusinessSubscriptionService = businessState.subscription.service;
const oldBusinessSubscriptionCost = businessState.subscription.cost;
setBusinessState({
purchase: {
service: [...oldBusinessPurchaseService, newService],
cost: [...oldBusinessPurchaseCost, newPCost]
},
subscription: {
service: [...oldBusinessSubscriptionService, newService],
cost: [...oldBusinessSubscriptionCost, newCost]
}
});
}
if (
name === "business" &&
businessState.subscription.service[0] !== undefined &&
Object.values(businessState.subscription.service).includes(newService)
) {
const removeBusinessIndex = businessState.subscription.service.indexOf(
newService
);
const reducedBusinessSubscriptionService = businessState.subscription.service.filter(
(s, i) => i !== removeBusinessIndex
);
const reducedBusinessSubscriptionCost = businessState.subscription.cost.filter(
(s, i) => i !== removeBusinessIndex
);
const reducedBusinessPurchaseService = businessState.purchase.service.filter(
(s, i) => i !== removeBusinessIndex
);
const reducedBusinessPurchaseCost = businessState.purchase.cost.filter(
(s, i) => i !== removeBusinessIndex
);
setBusinessState({
purchase: {
service: [...reducedBusinessPurchaseService],
cost: [...reducedBusinessPurchaseCost]
},
subscription: {
service: [...reducedBusinessSubscriptionService],
cost: [...reducedBusinessSubscriptionCost]
}
});
}
if (
name === "business" &&
businessState.subscription.service[0] === undefined
) {
setBusinessState({
purchase: {
service: [newService],
cost: [newPCost]
},
subscription: {
service: [newService],
cost: [newCost]
}
});
}
if (
name === "information" &&
informationState.subscription.service[0] !== undefined &&
!Object.values(informationState.subscription.service).includes(newService)
) {
const oldInformationPurchaseService = informationState.purchase.service;
const oldInformationPurchaseCost = informationState.purchase.cost;
const oldInformationSubscriptionService =
informationState.subscription.service;
const oldInformationSubscriptionCost = informationState.subscription.cost;
setInformationState({
purchase: {
service: [...oldInformationPurchaseService, newService],
cost: [...oldInformationPurchaseCost, newPCost]
},
subscription: {
service: [...oldInformationSubscriptionService, newService],
cost: [...oldInformationSubscriptionCost, newCost]
}
});
}
if (
name === "information" &&
informationState.subscription.service[0] !== undefined &&
Object.values(informationState.subscription.service).includes(newService)
) {
const removeInformationIndex = informationState.subscription.service.indexOf(
newService
);
const reducedInformationSubscriptionService = informationState.subscription.service.filter(
(s, i) => i !== removeInformationIndex
);
const reducedInformationSubscriptionCost = informationState.subscription.cost.filter(
(s, i) => i !== removeInformationIndex
);
const reducedInformationPurchaseService = informationState.purchase.service.filter(
(s, i) => i !== removeInformationIndex
);
const reducedInformationPurchaseCost = informationState.purchase.cost.filter(
(s, i) => i !== removeInformationIndex
);
setInformationState({
purchase: {
service: [...reducedInformationPurchaseService],
cost: [...reducedInformationPurchaseCost]
},
subscription: {
service: [...reducedInformationSubscriptionService],
cost: [...reducedInformationSubscriptionCost]
}
});
}
if (
name === "information" &&
informationState.subscription.service[0] === undefined
) {
setInformationState({
purchase: {
service: [newService],
cost: [newPCost]
},
subscription: {
service: [newService],
cost: [newCost]
}
});
}
if (
name === "ecommerce" &&
ecommerceState.subscription.service[0] !== undefined &&
!Object.values(ecommerceState.subscription.service).includes(newService)
) {
const oldEcommercePurchaseService = ecommerceState.purchase.service;
const oldEcommercePurchaseCost = ecommerceState.purchase.cost;
const oldEcommerceSubscriptionService =
ecommerceState.subscription.service;
const oldEcommerceSubscriptionCost = ecommerceState.subscription.cost;
setEcommerceState({
purchase: {
service: [...oldEcommercePurchaseService, newService],
cost: [...oldEcommercePurchaseCost, newPCost]
},
subscription: {
service: [...oldEcommerceSubscriptionService, newService],
cost: [...oldEcommerceSubscriptionCost, newCost]
}
});
}
if (
name === "ecommerce" &&
ecommerceState.subscription.service[0] !== undefined &&
Object.values(ecommerceState.subscription.service).includes(newService)
) {
const removeEcommerceIndex = ecommerceState.subscription.service.indexOf(
newService
);
const reducedEcommerceSubscriptionService = ecommerceState.subscription.service.filter(
(s, i) => i !== removeEcommerceIndex
);
const reducedEcommerceSubscriptionCost = ecommerceState.subscription.cost.filter(
(s, i) => i !== removeEcommerceIndex
);
const reducedEcommercePurchaseService = ecommerceState.purchase.service.filter(
(s, i) => i !== removeEcommerceIndex
);
const reducedEcommercePurchaseCost = ecommerceState.purchase.cost.filter(
(s, i) => i !== removeEcommerceIndex
);
setEcommerceState({
purchase: {
service: [...reducedEcommercePurchaseService],
cost: [...reducedEcommercePurchaseCost]
},
subscription: {
service: [...reducedEcommerceSubscriptionService],
cost: [...reducedEcommerceSubscriptionCost]
}
});
}
if (
name === "ecommerce" &&
ecommerceState.subscription.service[0] === undefined
) {
setEcommerceState({
purchase: {
service: [newService],
cost: [newPCost]
},
subscription: {
service: [newService],
cost: [newCost]
}
});
}
};
const data = state.data;
const activeStatus = state.active;
const pricingCarouselOptions = {
type: "slider",
perView: 3,
gap: 30,
bound: true,
breakpoints: {
1199: {
perView: 2,
type: "carousel",
peek: {
before: 100,
after: 100
}
},
990: {
type: "carousel",
perView: 1,
peek: {
before: 160,
after: 160
}
},
767: {
type: "carousel",
perView: 1,
peek: {
before: 80,
after: 80
}
},
575: {
type: "carousel",
perView: 1,
gap: 15,
peek: {
before: 20,
after: 20
}
}
}
};
return (
<Box {...sectionWrapper} id="pricing_section">
<Container>
<Box {...secTitleWrapper}>
<Text {...secText} content="PRICING PLAN" />
<Heading
{...secHeading}
content="Customize your website according to your needs"
/>
<PricingButtonWrapper>
<Button
title="Monthly Subscription Pricing"
className={activeStatus ? "active-item" : ""}
onClick={() =>
setState({ data: MONTHLY_PRICING_TABLE, active: true })
}
/>
<Button
title="One-Time Purchase Pricing"
className={activeStatus === false ? "active-item" : ""}
onClick={() =>
setState({ data: YEARLY_PRICING_TABLE, active: false })
}
/>
<Link href="#">
<a>+ Custom Plan</a>
</Link>
</PricingButtonWrapper>
</Box>
<PricingTableWrapper>
<GlideCarousel
carouselSelector="pricing-carousel"
options={pricingCarouselOptions}
controls={false}
>
<>
{data.map((pricingTable, index) => (
<GlideSlide key={`pricing-table-${index}`}>
<PricingTable
freePlan={pricingTable.freePlan}
className="pricing_table"
>
<PricingHead>
<Heading content={pricingTable.name} {...nameStyle} />
<Text
content={pricingTable.description}
{...descriptionStyle}
/>
</PricingHead>
<PricingPrice>
{pricingTable.name === "Informational Website" &&
pricingTable.type === "subscription" ? (
<Text
content={`$${informationTotal.subscription}`}
{...priceStyle}
/>
) : pricingTable.name === "Informational Website" &&
pricingTable.type === "purchase" ? (
<Text
content={`$${informationTotal.purchase}`}
{...priceStyle}
/>
) : pricingTable.name === "Business Website" &&
pricingTable.type === "subscription" ? (
<Text
content={`$${businessTotal.subscription}`}
{...priceStyle}
/>
) : pricingTable.name === "Business Website" &&
pricingTable.type === "purchase" ? (
<Text
content={`$${businessTotal.purchase}`}
{...priceStyle}
/>
) : pricingTable.category === "ecommerce" &&
pricingTable.type === "subscription" ? (
<Text
content={`$${ecommerceTotal.subscription}`}
{...priceStyle}
/>
) : pricingTable.category === "ecommerce" &&
pricingTable.type === "purchase" ? (
<Text
content={`$${ecommerceTotal.purchase}`}
{...priceStyle}
/>
) : (
<Text content="error" {...priceStyle} />
)}
<Text
content={pricingTable.priceLabel}
{...priceLabelStyle}
/>
</PricingPrice>
<PricingList>
{pricingTable.listItems.map((item, index) => (
<ListItem key={`pricing-table-list-${index}`}>
<Checkbox
name={`${pricingTable.category}`}
id={`${pricingTable.type}`}
labelText={item.service}
checked={toggleValue}
value={item}
onChange={e => {
toggleHandler;
handleChecking(e, item);
}}
// onChange={e => {
// toggleHandler;
// handleChecking(e);
// }}
/>
{/* <Text content={item.content} {...listContentStyle} /> */}
{pricingTable.type === "subscription" ? (
<Text
content={`$${item.cost}`}
{...listContentStyle}
/>
) : (
<Text
content={`$${item.pcost}`}
{...listContentStyle}
/>
)}
</ListItem>
))}
</PricingList>
<PricingButton>
<Link href={pricingTable.url}>
<a>
<Button
title={pricingTable.buttonLabel}
{...buttonFillStyle}
/>
</a>
</Link>
{pricingTable.trialButtonLabel ? (
<Link href={pricingTable.trialURL || "#"}>
<a className="trial_button">
{pricingTable.trialButtonLabel}
</a>
</Link>
) : (
""
)}
</PricingButton>
</PricingTable>
</GlideSlide>
))}
</>
</GlideCarousel>
</PricingTableWrapper>
</Container>
</Box>
);
};
export default PricingSection;
数据示例:
{
name: "Informational Website",
category: "information",
type: "subscription",
description:
" Beautiful landing page for small businesses or personal portfolios",
price: "$0",
priceLabel: "Per month",
buttonLabel: "Start for free",
url: "#",
listItems: [
{
service: ["Mobile-ready, Responsive Design"],
cost: [6],
pcost: [600]
},
{
service: ["Blog Articles"],
cost: [14],
pcost: [1300]
},
{
service: ["Collect visitor information (email / phone)"],
cost: [10],
pcost: [1000]
},
{
service: ["eCommerce Store "],
cost: [25],
pcost: [3200]
},
{
service: ["30+ Webmaster Tools"],
cost: [2],
pcost: [500]
}
]
},