fix: Zustand selector anti-pattern causing infinite re-render + plugin loader path
- Fix usePluginStore(s => s.getAll*()) selectors that returned new arrays on every call, causing infinite re-render loops and permanent spinner - Affected: Sidebar, Settings, ContactDetail, ContactEditModal, PluginRouteRenderer - Use usePluginStore(s => s.manifests) + useMemo instead - Fix PluginRouteRenderer: show spinner instead of null when manifests loading - Fix PluginLoader: @/ path replacement ../ -> ../../ for correct dynamic imports
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Badge } from '@/components/ui/Badge';
|
||||
@@ -157,7 +157,14 @@ export function ContactDetail({ contact, loading, onEdit, onDeleted }: ContactDe
|
||||
const [personModalOpen, setPersonModalOpen] = useState(false);
|
||||
const [editingPerson, setEditingPerson] = useState<ContactPerson | null>(null);
|
||||
const [activeTab, setActiveTab] = useState('details');
|
||||
const pluginTabs = usePluginStore(s => s.getDetailTabsForEntity('contact'));
|
||||
const manifests = usePluginStore(s => s.manifests);
|
||||
const pluginTabs = useMemo(
|
||||
() => manifests
|
||||
.flatMap((m) => m.detail_tabs)
|
||||
.filter((t) => t.entity_type === 'contact')
|
||||
.sort((a, b) => a.order - b.order),
|
||||
[manifests]
|
||||
);
|
||||
const aiActiveTab = useAIUIControlStore(s => s.activeTab);
|
||||
const aiActiveModal = useAIUIControlStore(s => s.activeModal);
|
||||
|
||||
@@ -180,7 +187,12 @@ export function ContactDetail({ contact, loading, onEdit, onDeleted }: ContactDe
|
||||
const user = useAuthStore(s => s.user);
|
||||
|
||||
// Custom fields from plugin definitions
|
||||
const customFieldDefs = usePluginStore(s => s.getCustomFieldsForEntity('contact'));
|
||||
const customFieldDefs = useMemo(
|
||||
() => manifests
|
||||
.flatMap((m) => m.custom_fields || [])
|
||||
.filter((cf) => cf.entity === 'contact'),
|
||||
[manifests]
|
||||
);
|
||||
const { data: customFieldsData } = useCustomFields(contact?.id);
|
||||
|
||||
if (loading) {
|
||||
|
||||
Reference in New Issue
Block a user