@@ -91,8 +91,11 @@ const normalizeForKey = (value: any): any => {
9191 return value ;
9292} ;
9393
94+ const makeQueryScopeKey = ( collection : string , queryParams : unknown ) =>
95+ `${ collection } |${ JSON . stringify ( normalizeForKey ( queryParams ) ) } ` ;
96+
9497const makeQueryKey = ( collection : string , queryParams : unknown , refreshToken = 0 ) =>
95- `${ collection } | ${ JSON . stringify ( normalizeForKey ( queryParams ) ) } |refresh:${ refreshToken } ` ;
98+ `${ makeQueryScopeKey ( collection , queryParams ) } |refresh:${ refreshToken } ` ;
9699
97100const acquireQuery = < T > (
98101 collection : string ,
@@ -124,9 +127,12 @@ const releaseQuery = (key?: string, cb?: () => void) => {
124127 cb ?.( ) ;
125128} ;
126129
127- const getRecordCollectionTableId = ( collection : string ) : string | undefined => {
130+ const getSchemaRefreshCollectionTableId = ( collection : string ) : string | undefined => {
128131 const [ prefix , tableId ] = collection . split ( '_' ) ;
129- if ( prefix !== IdPrefix . Record || ! tableId ) {
132+ if (
133+ ( prefix !== IdPrefix . Record && prefix !== IdPrefix . Field && prefix !== IdPrefix . View ) ||
134+ ! tableId
135+ ) {
130136 return undefined ;
131137 }
132138 return tableId ;
@@ -201,10 +207,12 @@ export function useInstances<T, R extends { id: string }>({
201207 initData,
202208} : IUseInstancesProps < T , R > ) : IInstanceState < R > {
203209 const { connection, connected } = useConnection ( ) ;
204- const recordCollectionTableId = getRecordCollectionTableId ( collection ) ;
210+ const schemaRefreshCollectionTableId = getSchemaRefreshCollectionTableId ( collection ) ;
205211 const [ query , setQuery ] = useState < Query < T > > ( ) ;
206212 const [ schemaRefreshToken , setSchemaRefreshToken ] = useState ( 0 ) ;
207213 const currentKeyRef = useRef < string > ( ) ;
214+ const currentScopeKeyRef = useRef < string > ( ) ;
215+ const shouldClearInstancesOnQueryCleanupRef = useRef ( true ) ;
208216 const [ instances , dispatch ] = useReducer (
209217 ( state : IInstanceState < R > , action : IInstanceAction < T > ) =>
210218 instanceReducer ( state , action , factory ) ,
@@ -218,12 +226,12 @@ export function useInstances<T, R extends { id: string }>({
218226 const lastConnectionRef = useRef < typeof connection > ( ) ;
219227
220228 useEffect ( ( ) => {
221- if ( ! connection || ! recordCollectionTableId ) {
229+ if ( ! connection || ! schemaRefreshCollectionTableId ) {
222230 return ;
223231 }
224232
225233 const presence : Presence = connection . getPresence (
226- getActionTriggerChannel ( recordCollectionTableId )
234+ getActionTriggerChannel ( schemaRefreshCollectionTableId )
227235 ) ;
228236 if ( ! presence . subscribed ) {
229237 presence . subscribe ( ( error ) => {
@@ -234,7 +242,7 @@ export function useInstances<T, R extends { id: string }>({
234242 }
235243
236244 const receiveListener = ( _id : string , batch : unknown ) => {
237- if ( ! isSchemaRefreshAction ( recordCollectionTableId , batch ) ) {
245+ if ( ! isSchemaRefreshAction ( schemaRefreshCollectionTableId , batch ) ) {
238246 return ;
239247 }
240248 setSchemaRefreshToken ( ( current ) => current + 1 ) ;
@@ -249,7 +257,7 @@ export function useInstances<T, R extends { id: string }>({
249257 presence . destroy ( ) ;
250258 }
251259 } ;
252- } , [ connection , recordCollectionTableId ] ) ;
260+ } , [ connection , schemaRefreshCollectionTableId ] ) ;
253261
254262 const handleReady = useCallback ( ( query : Query < T > ) => {
255263 console . log (
@@ -315,12 +323,15 @@ export function useInstances<T, R extends { id: string }>({
315323
316324 useEffect ( ( ) => {
317325 if ( ! collection || ! connection ) {
326+ shouldClearInstancesOnQueryCleanupRef . current = true ;
327+ currentScopeKeyRef . current = undefined ;
318328 setQuery ( undefined ) ;
319329 return ;
320330 }
321331
322332 // Compute normalized key and short-circuit if unchanged and connection didn't change
323333 const nextKey = makeQueryKey ( collection , queryParams , schemaRefreshToken ) ;
334+ const nextScopeKey = makeQueryScopeKey ( collection , queryParams ) ;
324335 const connectionChanged = lastConnectionRef . current !== connection ;
325336 if ( ! connectionChanged && currentKeyRef . current === nextKey && preQueryRef . current ) {
326337 // Ensure state holds the existing query instance without re-acquiring
@@ -329,12 +340,16 @@ export function useInstances<T, R extends { id: string }>({
329340 }
330341
331342 const previousKey = currentKeyRef . current ;
343+ const previousScopeKey = currentScopeKeyRef . current ;
344+ shouldClearInstancesOnQueryCleanupRef . current =
345+ connectionChanged || previousScopeKey !== nextScopeKey ;
332346 if ( previousKey && ( connectionChanged || previousKey !== nextKey ) ) {
333347 releaseQuery ( previousKey , ( ) => opListeners . current . clear ( ) ) ;
334348 }
335349
336350 const { key, query } = acquireQuery < T > ( collection , connection , queryParams , schemaRefreshToken ) ;
337351 currentKeyRef . current = key ;
352+ currentScopeKeyRef . current = nextScopeKey ;
338353 preQueryRef . current = query as Query < T > ;
339354 lastConnectionRef . current = connection ;
340355 setQuery ( query as Query < T > ) ;
@@ -349,8 +364,10 @@ export function useInstances<T, R extends { id: string }>({
349364 if ( ! hasQuery ) {
350365 return ;
351366 }
352- // for easy component refresh clean data when switch & loading
353- dispatch ( { type : 'clear' } ) ;
367+ // Preserve current instances during same-scope schema refreshes so grids do not flash blank.
368+ if ( shouldClearInstancesOnQueryCleanupRef . current ) {
369+ dispatch ( { type : 'clear' } ) ;
370+ }
354371 // release cached query on unmount or when switching queries
355372 releaseQuery ( keyAtMount , ( ) => listeners . clear ( ) ) ;
356373 } ;
0 commit comments