fix: dublicate api calls fixed
This commit is contained in:
+59
-23
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
import { packagesApi } from '@/lib/api/packages';
|
||||
import { productsApi } from '@/lib/api/products';
|
||||
@@ -17,27 +17,26 @@ export default function ProductsPage() {
|
||||
const [products, setProducts] = useState<Product[]>([]);
|
||||
const [selectedProduct, setSelectedProduct] = useState<Product | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isLoadingPackages, setIsLoadingPackages] = useState(false);
|
||||
const [isFormVisible, setIsFormVisible] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [success, setSuccess] = useState<string | null>(null);
|
||||
|
||||
// Load packages on mount
|
||||
// Use refs to track initial loads and prevent duplicate calls
|
||||
const initialLoadRef = useRef(false);
|
||||
const prevPackageRef = useRef<string | null>(null);
|
||||
|
||||
// Load packages on mount - only once
|
||||
useEffect(() => {
|
||||
if (token) {
|
||||
if (token && !initialLoadRef.current) {
|
||||
initialLoadRef.current = true;
|
||||
loadPackages();
|
||||
}
|
||||
}, [token]);
|
||||
|
||||
// Load products when package is selected
|
||||
useEffect(() => {
|
||||
if (selectedPackage && token) {
|
||||
loadProducts(selectedPackage.name!);
|
||||
} else {
|
||||
setProducts([]);
|
||||
}
|
||||
}, [selectedPackage, token]);
|
||||
|
||||
const loadPackages = async () => {
|
||||
setIsLoadingPackages(true);
|
||||
setError(null);
|
||||
try {
|
||||
const data = await packagesApi.getAllPackages(token!);
|
||||
setPackages(data);
|
||||
@@ -46,13 +45,24 @@ export default function ProductsPage() {
|
||||
}
|
||||
} catch (err) {
|
||||
setError('خطا در دریافت لیست پکیجها');
|
||||
} finally {
|
||||
setIsLoadingPackages(false);
|
||||
}
|
||||
};
|
||||
|
||||
const loadProducts = async (packageName: string) => {
|
||||
const loadProducts = useCallback(async (packageName: string, force = false) => {
|
||||
// Prevent duplicate loads of the same package
|
||||
if (!force && prevPackageRef.current === packageName) {
|
||||
console.log('Skipping duplicate load for package:', packageName);
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
prevPackageRef.current = packageName;
|
||||
|
||||
try {
|
||||
console.log('Loading products for package:', packageName);
|
||||
const data = await productsApi.getProducts(packageName, token!);
|
||||
setProducts(data);
|
||||
} catch (err) {
|
||||
@@ -60,13 +70,24 @@ export default function ProductsPage() {
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
}, [token]);
|
||||
|
||||
// Load products when package changes - with proper dependency
|
||||
useEffect(() => {
|
||||
if (selectedPackage?.name && token) {
|
||||
loadProducts(selectedPackage.name);
|
||||
} else {
|
||||
setProducts([]);
|
||||
}
|
||||
}, [selectedPackage?.name, token, loadProducts]);
|
||||
|
||||
const handlePackageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const pkg = packages.find(p => p.name === e.target.value);
|
||||
setSelectedPackage(pkg || null);
|
||||
setIsFormVisible(false);
|
||||
setSelectedProduct(null);
|
||||
setError(null);
|
||||
setSuccess(null);
|
||||
};
|
||||
|
||||
const handleCreate = () => {
|
||||
@@ -93,7 +114,11 @@ export default function ProductsPage() {
|
||||
try {
|
||||
await productsApi.deleteProduct(selectedPackage.name!, product.id, token!);
|
||||
setSuccess('محصول با موفقیت حذف شد');
|
||||
await loadProducts(selectedPackage.name!);
|
||||
// Force reload products after delete
|
||||
if (selectedPackage.name) {
|
||||
prevPackageRef.current = null; // Reset ref to force load
|
||||
await loadProducts(selectedPackage.name, true);
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'خطا در حذف محصول');
|
||||
} finally {
|
||||
@@ -119,7 +144,12 @@ export default function ProductsPage() {
|
||||
setSuccess('محصول با موفقیت ایجاد شد');
|
||||
}
|
||||
|
||||
await loadProducts(selectedPackage.name!);
|
||||
// Force reload products after create/update
|
||||
if (selectedPackage.name) {
|
||||
prevPackageRef.current = null; // Reset ref to force load
|
||||
await loadProducts(selectedPackage.name, true);
|
||||
}
|
||||
|
||||
setIsFormVisible(false);
|
||||
setSelectedProduct(null);
|
||||
} catch (err) {
|
||||
@@ -154,13 +184,18 @@ export default function ProductsPage() {
|
||||
id="package"
|
||||
value={selectedPackage?.name || ''}
|
||||
onChange={handlePackageChange}
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
disabled={isLoadingPackages}
|
||||
className="block w-full px-3 py-2 text-slate-900 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm disabled:opacity-50"
|
||||
>
|
||||
{packages.map((pkg) => (
|
||||
<option key={pkg.id} value={pkg.name || ''}>
|
||||
{pkg.title} ({pkg.name})
|
||||
</option>
|
||||
))}
|
||||
{isLoadingPackages ? (
|
||||
<option>در حال بارگذاری پکیجها...</option>
|
||||
) : (
|
||||
packages.map((pkg) => (
|
||||
<option key={pkg.id} value={pkg.name || ''}>
|
||||
{pkg.title} ({pkg.name})
|
||||
</option>
|
||||
))
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -184,7 +219,8 @@ export default function ProductsPage() {
|
||||
<div className="mb-4 flex justify-end">
|
||||
<button
|
||||
onClick={handleCreate}
|
||||
className="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
disabled={isLoading}
|
||||
className="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
|
||||
>
|
||||
<PlusIcon className="h-5 w-5 ml-2" />
|
||||
محصول جدید
|
||||
|
||||
Reference in New Issue
Block a user