fix: stop os persistent slot state recursion
This commit is contained in:
@@ -116,6 +116,22 @@ function sanitizeSlotState(state: SlotState | null, fallback: SlotState | null =
|
|||||||
return migrated ?? fallback;
|
return migrated ?? fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function areSlotStatesEqual(a: SlotState | null, b: SlotState | null): boolean {
|
||||||
|
if (a === b) return true;
|
||||||
|
if (!a || !b) return a === b;
|
||||||
|
if (a.activeTabId !== b.activeTabId) return false;
|
||||||
|
if (a.tabs.length !== b.tabs.length) return false;
|
||||||
|
|
||||||
|
return a.tabs.every((tab, index) => {
|
||||||
|
const other = b.tabs[index];
|
||||||
|
return (
|
||||||
|
tab.id === other?.id &&
|
||||||
|
tab.type === other?.type &&
|
||||||
|
tab.nodeId === other?.nodeId
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getSlotTabsByType(state: SlotState | null, type: PaneType): SlotTab[] {
|
function getSlotTabsByType(state: SlotState | null, type: PaneType): SlotTab[] {
|
||||||
return state?.tabs.filter((tab) => tab.type === type) ?? [];
|
return state?.tabs.filter((tab) => tab.type === type) ?? [];
|
||||||
}
|
}
|
||||||
@@ -167,9 +183,18 @@ export default function ThreePanelLayout() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSlotA((prev) => sanitizeSlotState(prev, DEFAULT_SLOT_A));
|
setSlotA((prev) => {
|
||||||
setSlotB((prev) => sanitizeSlotState(prev));
|
const next = sanitizeSlotState(prev, DEFAULT_SLOT_A);
|
||||||
setSlotC((prev) => sanitizeSlotState(prev));
|
return areSlotStatesEqual(prev, next) ? prev : next;
|
||||||
|
});
|
||||||
|
setSlotB((prev) => {
|
||||||
|
const next = sanitizeSlotState(prev);
|
||||||
|
return areSlotStatesEqual(prev, next) ? prev : next;
|
||||||
|
});
|
||||||
|
setSlotC((prev) => {
|
||||||
|
const next = sanitizeSlotState(prev);
|
||||||
|
return areSlotStatesEqual(prev, next) ? prev : next;
|
||||||
|
});
|
||||||
}, [setSlotA, setSlotB, setSlotC]);
|
}, [setSlotA, setSlotB, setSlotC]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
|
|
||||||
export function usePersistentState<T>(
|
export function usePersistentState<T>(
|
||||||
key: string,
|
key: string,
|
||||||
@@ -22,7 +22,7 @@ export function usePersistentState<T>(
|
|||||||
}, [key]);
|
}, [key]);
|
||||||
|
|
||||||
// Save to localStorage when state changes
|
// Save to localStorage when state changes
|
||||||
const setPersistentState = (value: T | ((prev: T) => T)) => {
|
const setPersistentState = useCallback((value: T | ((prev: T) => T)) => {
|
||||||
setState(prev => {
|
setState(prev => {
|
||||||
const newValue = typeof value === 'function'
|
const newValue = typeof value === 'function'
|
||||||
? (value as (prev: T) => T)(prev)
|
? (value as (prev: T) => T)(prev)
|
||||||
@@ -36,7 +36,7 @@ export function usePersistentState<T>(
|
|||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
});
|
});
|
||||||
};
|
}, [key]);
|
||||||
|
|
||||||
return [state, setPersistentState];
|
return [state, setPersistentState];
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user