Skip to content

Commit de609ec

Browse files
authored
fix: ensure $effect.tracking returns false inside transition functions (#13775)
1 parent 4a0c90e commit de609ec

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

.changeset/few-rocks-remain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure $effect.tracking returns false inside transition functions

packages/svelte/src/internal/client/dom/elements/transitions.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/** @import { AnimateFn, Animation, AnimationConfig, EachItem, Effect, TransitionFn, TransitionManager } from '#client' */
22
import { noop, is_function } from '../../../shared/utils.js';
33
import { effect } from '../../reactivity/effects.js';
4-
import { active_effect, untrack } from '../../runtime.js';
4+
import {
5+
active_effect,
6+
active_reaction,
7+
set_active_effect,
8+
set_active_reaction,
9+
untrack
10+
} from '../../runtime.js';
511
import { loop } from '../../loop.js';
612
import { should_intro } from '../../render.js';
713
import { current_each_item } from '../blocks/each.js';
@@ -185,12 +191,21 @@ export function transition(flags, element, get_fn, get_params) {
185191
var outro;
186192

187193
function get_options() {
188-
// If a transition is still ongoing, we use the existing options rather than generating
189-
// new ones. This ensures that reversible transitions reverse smoothly, rather than
190-
// jumping to a new spot because (for example) a different `duration` was used
191-
return (current_options ??= get_fn()(element, get_params?.() ?? /** @type {P} */ ({}), {
192-
direction
193-
}));
194+
var previous_reaction = active_reaction;
195+
var previous_effect = active_effect;
196+
set_active_reaction(null);
197+
set_active_effect(null);
198+
try {
199+
// If a transition is still ongoing, we use the existing options rather than generating
200+
// new ones. This ensures that reversible transitions reverse smoothly, rather than
201+
// jumping to a new spot because (for example) a different `duration` was used
202+
return (current_options ??= get_fn()(element, get_params?.() ?? /** @type {P} */ ({}), {
203+
direction
204+
}));
205+
} finally {
206+
set_active_reaction(previous_reaction);
207+
set_active_effect(previous_effect);
208+
}
194209
}
195210

196211
/** @type {TransitionManager} */
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target, logs }) {
6+
const b1 = target.querySelector('button');
7+
8+
b1?.click();
9+
flushSync();
10+
assert.deepEqual(logs, [false]);
11+
12+
b1?.click();
13+
flushSync();
14+
assert.deepEqual(logs, [false, false]);
15+
}
16+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
let visible = $state(0);
3+
4+
function customTransition() {
5+
console.log($effect.tracking());
6+
}
7+
</script>
8+
9+
<button onclick={() => visible = !visible}>Toggle</button>
10+
11+
{#if visible}
12+
<div transition:customTransition>clicks</div>
13+
{/if}

0 commit comments

Comments
 (0)