@@ -635,6 +635,13 @@ export function Table({
635635 return
636636 }
637637
638+ /** Creating a view updates the query cache before nuqs commits its URL id.
639+ * Keep the blank view already applied in the success handler during that
640+ * gap instead of briefly reapplying the previously selected view. */
641+ if ( pendingCreatedViewIdRef . current && activeViewId !== pendingCreatedViewIdRef . current ) {
642+ return
643+ }
644+
638645 // The id resolved, so any create race for it is over.
639646 if ( selectedView && pendingCreatedViewIdRef . current === selectedView . id ) {
640647 pendingCreatedViewIdRef . current = null
@@ -673,11 +680,6 @@ export function Table({
673680 if ( activeView && ( activeViewId === null || activeViewId === ALL_VIEW_PARAM ) ) {
674681 setTableParams ( { view : activeView . id } )
675682 }
676- // Navigating away ends any create race — without this a reconcile on the
677- // destination could fall back to the still-pending created id.
678- if ( pendingCreatedViewIdRef . current && pendingCreatedViewIdRef . current !== nextViewId ) {
679- pendingCreatedViewIdRef . current = null
680- }
681683 const keep = preserved ?. viewId === nextViewId ? preserved . keep : undefined
682684 applyViewConfig ( activeViewConfig , keep )
683685 if ( activeView ) flushPendingViewConfig ( activeView . id )
@@ -716,19 +718,6 @@ export function Table({
716718 [ columns . length , hiddenColumns , liveColumnIds ]
717719 )
718720
719- /**
720- * Drops a sort whose column was deleted by clearing the URL, rather than masking
721- * it in a derived value: `queryOptions` feeds the query that produces `columns`,
722- * so a pruned sort can't flow back into it without a cycle. Clearing keeps one
723- * source of truth, so the rows query and the active-view autosave cannot
724- * disagree about whether a sort is active.
725- */
726- useEffect ( ( ) => {
727- if ( ! sortColumn || columns . length === 0 ) return
728- if ( liveColumnIds . has ( sortColumn ) ) return
729- setTableParams ( { sort : null , dir : null } )
730- } , [ sortColumn , columns . length , liveColumnIds , setTableParams ] )
731-
732721 /** Rename targets a live view rather than a snapshot, so a concurrent rename or
733722 * delete can't leave the modal editing stale data. */
734723 const renamingView =
@@ -759,7 +748,7 @@ export function Table({
759748 */
760749 const persistActiveViewConfig = useCallback (
761750 ( configPatch : TableViewConfig ) => {
762- if ( ! userPermissions . canEdit ) return
751+ if ( ! viewsEnabled || ! userPermissions . canEdit ) return
763752 const viewId = activeView ?. id ?? pendingCreatedViewIdRef . current
764753 if ( ! viewId ) {
765754 if ( ! ownerResolvedRef . current ) {
@@ -779,9 +768,22 @@ export function Table({
779768 }
780769 )
781770 } ,
782- [ activeView ?. id , userPermissions . canEdit , releasePersistedViewState ]
771+ [ viewsEnabled , activeView ?. id , userPermissions . canEdit , releasePersistedViewState ]
783772 )
784773
774+ /**
775+ * Drops a sort whose column was deleted from both the URL and its persisted
776+ * view. `queryOptions` feeds the query that produces `columns`, so clearing the
777+ * source of truth avoids a dependency cycle and prevents the dead sort from
778+ * returning on reload.
779+ */
780+ useEffect ( ( ) => {
781+ if ( ! sortColumn || columns . length === 0 ) return
782+ if ( liveColumnIds . has ( sortColumn ) ) return
783+ setTableParams ( { sort : null , dir : null } )
784+ persistActiveViewConfig ( { sort : null } )
785+ } , [ sortColumn , columns . length , liveColumnIds , setTableParams , persistActiveViewConfig ] )
786+
785787 /** Column order/width/pinning auto-saves into the active view as the user drags.
786788 * Sent as a `configPatch` so the server merges it — two overlapping layout writes must
787789 * not each replace the whole blob from their own snapshot. With All selected
0 commit comments