suparisma 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1021,7 +1021,9 @@ export function createSuparismaHook<
1021
1021
  const searchTimeoutRef = useRef<NodeJS.Timeout | null>(null);
1022
1022
  const isSearchingRef = useRef<boolean>(false);
1023
1023
 
1024
- // Function to fetch the total count from Supabase with current filters
1024
+ // Function to fetch the total count from Supabase with current filters.
1025
+ // IMPORTANT: do NOT capture unstable objects (where/orderBy/etc) in deps.
1026
+ // Read the latest values from refs to avoid effect→setState→rerender loops.
1025
1027
  const fetchTotalCount = useCallback(async () => {
1026
1028
  try {
1027
1029
  // Skip count updates when disabled or during search
@@ -1030,25 +1032,23 @@ export function createSuparismaHook<
1030
1032
 
1031
1033
  let countQuery = supabase.from(tableName).select('*', { count: 'exact', head: true });
1032
1034
 
1033
- // Apply where conditions if provided
1034
- if (where) {
1035
- countQuery = applyFilter(countQuery, where);
1035
+ // Apply current where conditions via ref (NOT the captured 'where')
1036
+ const currentWhere = whereRef.current;
1037
+ if (currentWhere) {
1038
+ countQuery = applyFilter(countQuery, currentWhere);
1036
1039
  }
1037
1040
 
1038
1041
  const { count: totalCount, error: countError } = await countQuery;
1039
1042
 
1040
1043
  if (!countError) {
1041
- setCount(totalCount || 0);
1044
+ const nextCount = totalCount || 0;
1045
+ // Cheap guard to reduce churn
1046
+ setCount((prev) => (prev === nextCount ? prev : nextCount));
1042
1047
  }
1043
1048
  } catch (err) {
1044
1049
  console.error(\`Error fetching count for \${tableName}:\`, err);
1045
1050
  }
1046
- }, [where, tableName]);
1047
-
1048
- // Update total count whenever where filter changes
1049
- useEffect(() => {
1050
- fetchTotalCount();
1051
- }, [fetchTotalCount]);
1051
+ }, [tableName]);
1052
1052
 
1053
1053
  // Create the search state object with all required methods
1054
1054
  const search: SearchState = {
@@ -1455,17 +1455,17 @@ export function createSuparismaHook<
1455
1455
  }, []);
1456
1456
 
1457
1457
  // Set up realtime subscription for the list - ONCE and listen to ALL events
1458
+ const channelIdRef = useRef<string | null>(null);
1459
+
1458
1460
  useEffect(() => {
1459
1461
  // Skip subscription if not enabled or realtime is off
1460
1462
  if (!enabled || !realtime) return;
1461
1463
 
1462
- // Clean up previous subscription if it exists
1463
- if (channelRef.current) {
1464
- channelRef.current.unsubscribe();
1465
- channelRef.current = null;
1466
- }
1467
-
1468
- const channelId = channelName || \`changes_to_\${tableName}_\${Math.random().toString(36).substring(2, 15)}\`;
1464
+ // Stable channel id per hook instance (unless user explicitly provides channelName)
1465
+ const channelId =
1466
+ channelName ??
1467
+ channelIdRef.current ??
1468
+ (channelIdRef.current = \`changes_to_\${tableName}_\${generateUUID()}\`);
1469
1469
 
1470
1470
  // ALWAYS listen to ALL events and filter client-side for maximum reliability
1471
1471
  let subscriptionConfig: any = {
@@ -1744,13 +1744,15 @@ export function createSuparismaHook<
1744
1744
  console.log(\`Subscription status for \${tableName}\`, status);
1745
1745
  });
1746
1746
 
1747
- // Store the channel ref
1747
+ // Store the channel ref (for optional introspection)
1748
1748
  channelRef.current = channel;
1749
1749
 
1750
1750
  return () => {
1751
1751
  console.log(\`Unsubscribing from \${channelId}\`);
1752
- if (channelRef.current) {
1753
- supabase.removeChannel(channelRef.current); // Correct way to remove channel
1752
+ // Always remove the exact channel created by this effect instance
1753
+ supabase.removeChannel(channel);
1754
+ // Only clear the ref if it still matches (avoid races if effect re-runs)
1755
+ if (channelRef.current === channel) {
1754
1756
  channelRef.current = null;
1755
1757
  }
1756
1758