fix infinite loop in sidebar action effects with untrack

This commit is contained in:
Justin Edmund 2025-12-03 20:52:03 -08:00
parent eaae29f007
commit 8759afb83c
3 changed files with 36 additions and 15 deletions

View file

@ -8,6 +8,7 @@
* *
* The "My Collection" tab includes an edit mode using CharacterEditPane. * The "My Collection" tab includes an edit mode using CharacterEditPane.
*/ */
import { untrack } from 'svelte'
import type { CollectionCharacter, ExtendedMastery } from '$lib/types/api/collection' import type { CollectionCharacter, ExtendedMastery } from '$lib/types/api/collection'
import { useUpdateCollectionCharacter } from '$lib/api/mutations/collection.mutations' import { useUpdateCollectionCharacter } from '$lib/api/mutations/collection.mutations'
import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte' import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte'
@ -216,11 +217,17 @@
// Update sidebar header action based on current state // Update sidebar header action based on current state
$effect(() => { $effect(() => {
if (isOwner && selectedTab === 'collection' && !isEditing) { // Capture reactive dependencies we want to track
sidebar.setAction(() => (isEditing = true), 'Edit', elementName) const shouldShowEdit = isOwner && selectedTab === 'collection' && !isEditing
} else { const element = elementName
sidebar.clearAction() // Use untrack to avoid infinite loop when sidebar.setAction mutates pane state
} untrack(() => {
if (shouldShowEdit) {
sidebar.setAction(() => (isEditing = true), 'Edit', element)
} else {
sidebar.clearAction()
}
})
}) })
// Clean up sidebar action when component is destroyed // Clean up sidebar action when component is destroyed

View file

@ -8,6 +8,7 @@
* *
* The "My Collection" tab includes an edit mode using SummonEditPane. * The "My Collection" tab includes an edit mode using SummonEditPane.
*/ */
import { untrack } from 'svelte'
import type { CollectionSummon } from '$lib/types/api/collection' import type { CollectionSummon } from '$lib/types/api/collection'
import { useUpdateCollectionSummon } from '$lib/api/mutations/collection.mutations' import { useUpdateCollectionSummon } from '$lib/api/mutations/collection.mutations'
import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte' import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte'
@ -109,11 +110,17 @@
// Update sidebar header action // Update sidebar header action
$effect(() => { $effect(() => {
if (isOwner && selectedTab === 'collection' && !isEditing) { // Capture reactive dependencies we want to track
sidebar.setAction(() => (isEditing = true), 'Edit', elementName) const shouldShowEdit = isOwner && selectedTab === 'collection' && !isEditing
} else { const element = elementName
sidebar.clearAction() // Use untrack to avoid infinite loop when sidebar.setAction mutates pane state
} untrack(() => {
if (shouldShowEdit) {
sidebar.setAction(() => (isEditing = true), 'Edit', element)
} else {
sidebar.clearAction()
}
})
}) })
// Clean up sidebar action when component is destroyed // Clean up sidebar action when component is destroyed

View file

@ -8,6 +8,7 @@
* *
* The "My Collection" tab includes an edit mode using WeaponEditPane. * The "My Collection" tab includes an edit mode using WeaponEditPane.
*/ */
import { untrack } from 'svelte'
import type { CollectionWeapon } from '$lib/types/api/collection' import type { CollectionWeapon } from '$lib/types/api/collection'
import type { SimpleAxSkill } from '$lib/types/api/entities' import type { SimpleAxSkill } from '$lib/types/api/entities'
import { useUpdateCollectionWeapon } from '$lib/api/mutations/collection.mutations' import { useUpdateCollectionWeapon } from '$lib/api/mutations/collection.mutations'
@ -193,11 +194,17 @@
// Update sidebar header action // Update sidebar header action
$effect(() => { $effect(() => {
if (isOwner && selectedTab === 'collection' && !isEditing) { // Capture reactive dependencies we want to track
sidebar.setAction(() => (isEditing = true), 'Edit', elementName) const shouldShowEdit = isOwner && selectedTab === 'collection' && !isEditing
} else { const element = elementName
sidebar.clearAction() // Use untrack to avoid infinite loop when sidebar.setAction mutates pane state
} untrack(() => {
if (shouldShowEdit) {
sidebar.setAction(() => (isEditing = true), 'Edit', element)
} else {
sidebar.clearAction()
}
})
}) })
// Clean up sidebar action when component is destroyed // Clean up sidebar action when component is destroyed