refactor: optimize credits rendering by memoizing and moving checks before hooks

This commit is contained in:
javayhu 2025-07-24 00:50:23 +08:00
parent bc4578a3cd
commit 0d04f6914e
3 changed files with 21 additions and 12 deletions

View File

@ -2,18 +2,22 @@ import BillingCard from '@/components/settings/billing/billing-card';
import CreditsBalanceCard from '@/components/settings/billing/credits-balance-card'; import CreditsBalanceCard from '@/components/settings/billing/credits-balance-card';
import { CreditPackages } from '@/components/settings/credits/credit-packages'; import { CreditPackages } from '@/components/settings/credits/credit-packages';
import { websiteConfig } from '@/config/website'; import { websiteConfig } from '@/config/website';
import { useMemo } from 'react';
export default function BillingPage() { export default function BillingPage() {
// Memoize the credits enabled state to ensure consistency across renders
const creditsEnabled = useMemo(() => websiteConfig.credits.enableCredits, []);
return ( return (
<div className="space-y-8"> <div className="space-y-8">
{/* Billing and Credits Balance Cards */} {/* Billing and Credits Balance Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<BillingCard /> <BillingCard />
{websiteConfig.credits.enableCredits && <CreditsBalanceCard />} {creditsEnabled && <CreditsBalanceCard />}
</div> </div>
{/* Credit Packages */} {/* Credit Packages */}
{websiteConfig.credits.enableCredits && ( {creditsEnabled && (
<div className="w-full"> <div className="w-full">
<CreditPackages /> <CreditPackages />
</div> </div>

View File

@ -26,6 +26,11 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
export default function CreditsBalanceCard() { export default function CreditsBalanceCard() {
// Don't render if credits are disabled - move this check before any hooks
if (!websiteConfig.credits.enableCredits) {
return null;
}
const t = useTranslations('Dashboard.settings.credits.balance'); const t = useTranslations('Dashboard.settings.credits.balance');
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const localeRouter = useLocaleRouter(); const localeRouter = useLocaleRouter();
@ -109,11 +114,6 @@ export default function CreditsBalanceCard() {
fetchCreditStats(); fetchCreditStats();
}, [fetchCredits, fetchCreditStats]); }, [fetchCredits, fetchCreditStats]);
// Don't render if credits are disabled
if (!websiteConfig.credits.enableCredits) {
return null;
}
// Render loading skeleton // Render loading skeleton
const isPageLoading = isLoadingBalance || isLoadingStats; const isPageLoading = isLoadingBalance || isLoadingStats;
if (!mounted || isPageLoading) { if (!mounted || isPageLoading) {

View File

@ -23,12 +23,22 @@ import { CreditCheckoutButton } from './credit-checkout-button';
* @returns Credit packages component * @returns Credit packages component
*/ */
export function CreditPackages() { export function CreditPackages() {
// Check if credits are enabled - move this check before any hooks
if (!websiteConfig.credits.enableCredits) {
return null;
}
const t = useTranslations('Dashboard.settings.credits.packages'); const t = useTranslations('Dashboard.settings.credits.packages');
// Get current user and payment info // Get current user and payment info
const currentUser = useCurrentUser(); const currentUser = useCurrentUser();
const { currentPlan } = usePayment(); const { currentPlan } = usePayment();
// Get credit packages with translations - must be called here to maintain hook order
const creditPackages = Object.values(getCreditPackages()).filter(
(pkg) => !pkg.disabled && pkg.price.priceId
);
// Check if user is on free plan and enableForFreePlan is false // Check if user is on free plan and enableForFreePlan is false
const isFreePlan = currentPlan?.isFree === true; const isFreePlan = currentPlan?.isFree === true;
@ -37,11 +47,6 @@ export function CreditPackages() {
return null; return null;
} }
// show only enabled packages
const creditPackages = Object.values(getCreditPackages()).filter(
(pkg) => !pkg.disabled && pkg.price.priceId
);
return ( return (
<Card className="w-full"> <Card className="w-full">
<CardHeader> <CardHeader>