fix(form): break drawer counter/dirty infinite-loop + add GlobeLoader + AppErrorBoundary
Maximum update depth exceeded showed на /dictionaries/$name когда RecordDrawer
открывался в create mode. Root cause:
1. SchemaDrivenForm useEffect deps включал onCounterChange/onDirtyChange.
2. Parent route передавал inline arrow (() => setDrawerCount({...})) —
новая identity каждый render.
3. setDrawerCount({visible, total}) создавал новый object literal даже
при тех же значениях → React re-render → effect fires → loop.
Fix:
- SchemaDrivenForm: ref-pattern для callback. useEffect subscribed только
на value deps (visibleFieldCount/totalFieldCount/dirtyCount), latest
callback хранится в ref.
- dataValues — useMemo с frozen EMPTY_DATA default чтобы не invalidate'ить
isFieldVisible memo каждый render.
Plus:
- GlobeLoader component — orbital globe spinner per Downloads/Globe loader
prototype. Pure SVG + CSS animations, без d3/topojson.
- LoadingBlock переключен с Loader2 на GlobeLoader (все usage обновляется
автоматически: RecordHistoryDrawer, dictionaries.$name editor loading,
search results, webhooks list, etc).
- AppErrorBoundary — friendly fallback вместо TanStack DefaultErrorComponent.
GlobeLoader (paused/dimmed) + 'Что-то пошло не так' + [Обновить][На главную].
Dev-only collapsible с raw stack trace.
This commit is contained in:
@@ -4,6 +4,7 @@ import { useState } from 'react'
|
||||
import { Sidebar, MobileSidebar } from '@/components/layout/Sidebar'
|
||||
import { TopBar } from '@/components/layout/TopBar'
|
||||
import { UpdateBanner } from '@/components/version/UpdateBanner'
|
||||
import { AppErrorBoundary } from '@/components/layout/AppErrorBoundary'
|
||||
|
||||
/**
|
||||
* Root layout (Stage 3.1 + 3.x mobile responsive):
|
||||
@@ -24,6 +25,9 @@ import { UpdateBanner } from '@/components/version/UpdateBanner'
|
||||
*/
|
||||
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
|
||||
component: RootLayout,
|
||||
// Catch unhandled errors inside any route — show friendly UI instead of
|
||||
// TanStack default "Something went wrong! Hide Error" + raw stack trace.
|
||||
errorComponent: AppErrorBoundary,
|
||||
})
|
||||
|
||||
function RootLayout() {
|
||||
|
||||
Reference in New Issue
Block a user