refactor(webapp): simplify manual memoization

This commit is contained in:
Chris Arderne
2026-08-19 17:42:31 +01:00
parent 3da30d8b57
commit 9683be901a
4 changed files with 14 additions and 10 deletions
@@ -140,14 +140,18 @@ export function BillingAlertsSection({
);
const maxAlerts = isPercentageMode ? MAX_PERCENTAGE_ALERTS : MAX_ABSOLUTE_ALERTS;
/* oxlint-disable react/react-compiler -- Stable derived thresholds prevent the synchronization effect from resetting local edits. */
const savedThresholds = useMemo(
() => storedAlertsToThresholds(alerts, billingLimitMode, effectiveLimitCents, planLimitCents),
[alerts, billingLimitMode, effectiveLimitCents, planLimitCents]
);
/* oxlint-enable react/react-compiler */
const savedEmails = useMemo(() => alerts.emails, [alerts.emails]);
const hasLegacySpikes = useMemo(
() => hasLegacySpikeAlertLevels(alerts, billingLimitMode, effectiveLimitCents, planLimitCents),
[alerts, billingLimitMode, effectiveLimitCents, planLimitCents]
const hasLegacySpikes = hasLegacySpikeAlertLevels(
alerts,
billingLimitMode,
effectiveLimitCents,
planLimitCents
);
const nextThresholdIdRef = useRef(savedThresholds.length);
@@ -416,6 +416,7 @@ export function DashboardAgentPanel({
}, []);
const dismissWatchCard = () => dispatchWatchCard({ type: "dismissed" });
const activeChatId = active?.chatId;
const submitWatch = useCallback(async () => {
const draft = watchCard.draft;
@@ -429,7 +430,7 @@ export function DashboardAgentPanel({
body.set("draft", JSON.stringify(draft));
body.set("clientRequestId", clientRequestId);
// A watch is chat-bound: with no chat open the server creates one.
if (active?.chatId) body.set("chatId", active.chatId);
if (activeChatId) body.set("chatId", activeChatId);
const res = await fetch(actionPath, { method: "POST", body });
const data = (await res.json()) as {
@@ -446,7 +447,7 @@ export function DashboardAgentPanel({
}
const messages = data.messages;
if (active?.chatId === data.chatId) {
if (activeChatId === data.chatId) {
setAppendedMessages((current) => ({
chatId: data.chatId!,
messages,
@@ -474,7 +475,7 @@ export function DashboardAgentPanel({
}, [
watchCard.draft,
watchCard.requestId,
active?.chatId,
activeChatId,
actionPath,
organization.id,
claimChatSlot,
@@ -257,6 +257,7 @@ export function useDashboardEditor({
// Sync queue processor - ensures only one sync runs at a time
// -------------------------------------------------------------------------
/* oxlint-disable react/react-compiler -- The recursive callback drains a serialized sync queue. */
const processNextSync = useCallback(async () => {
// If already syncing or queue is empty, do nothing
if (isSyncingRef.current || syncQueueRef.current.length === 0) {
@@ -309,6 +310,7 @@ export function useDashboardEditor({
processNextSync();
}
}, [widgetActionUrl, layoutActionUrl, onSyncError]);
/* oxlint-enable react/react-compiler */
// -------------------------------------------------------------------------
// Queue helpers
@@ -1430,10 +1430,7 @@ function QueueEnvMetricChart({
[tile.id, tile.label, lineColor]
);
const { tickFormatter, tooltipLabelFormatter } = useMemo(
() => buildActivityTimeAxis(data),
[data]
);
const { tickFormatter, tooltipLabelFormatter } = buildActivityTimeAxis(data);
const hasData = data.length > 0 && data.some((p) => Number(p[tile.id] ?? 0) > 0);
// Peak readout lives in the card title (ChartCard has no dedicated value slot). A zero/empty