add a way to run code when the current reaction finishes updating

source-to-state-in-class-belt-and-braces
Rich Harris 2 months ago
parent f261686140
commit 67dc9b27b4

@ -1,6 +1,12 @@
/** @import { Derived, Effect, Reaction, Signal, Source, Value } from '#client' */
import { DEV } from 'esm-env';
import { define_property, get_descriptors, get_prototype_of, index_of } from '../shared/utils.js';
import {
define_property,
get_descriptors,
get_prototype_of,
index_of,
run_all
} from '../shared/utils.js';
import {
destroy_block_effect_children,
destroy_effect_children,
@ -56,6 +62,17 @@ export function set_is_destroying_effect(value) {
is_destroying_effect = value;
}
/** @type {Array<() => void> | null} */
let updated_callbacks = null;
/**
* Run `fn` when the current reaction finishes updating
* @param {() => void} fn
*/
export function onupdated(fn) {
(updated_callbacks ??= []).push(fn);
}
// Handle effect queues
/** @type {Effect[]} */
@ -265,6 +282,7 @@ export function update_reaction(reaction) {
var previous_reaction_sources = source_ownership;
var previous_component_context = component_context;
var previous_untracking = untracking;
var previous_updated_callbacks = updated_callbacks;
var flags = reaction.f;
@ -358,6 +376,10 @@ export function update_reaction(reaction) {
} catch (error) {
handle_error(error);
} finally {
if (updated_callbacks !== null) {
run_all(updated_callbacks);
}
new_deps = previous_deps;
skipped_deps = previous_skipped_deps;
untracked_writes = previous_untracked_writes;
@ -366,6 +388,7 @@ export function update_reaction(reaction) {
source_ownership = previous_reaction_sources;
set_component_context(previous_component_context);
untracking = previous_untracking;
updated_callbacks = previous_updated_callbacks;
reaction.f ^= EFFECT_IS_UPDATING;
}

@ -2,7 +2,7 @@
import { DEV } from 'esm-env';
import { set, source, state } from '../internal/client/reactivity/sources.js';
import { label, tag } from '../internal/client/dev/tracing.js';
import { active_reaction, get } from '../internal/client/runtime.js';
import { active_reaction, get, onupdated } from '../internal/client/runtime.js';
import { increment } from './utils.js';
import { teardown } from '../internal/client/reactivity/effects.js';
@ -68,9 +68,10 @@ export class SvelteMap extends Map {
if (active_reaction !== null) {
this.#initial_reaction = active_reaction;
// since we only need `initial_reaction` as long as we are in a derived/effect we can
// safely create a teardown function that will reset it to null and allow for GC
teardown(() => {
onupdated(() => {
this.#initial_reaction = null;
});
}

@ -2,7 +2,7 @@
import { DEV } from 'esm-env';
import { source, set, state } from '../internal/client/reactivity/sources.js';
import { label, tag } from '../internal/client/dev/tracing.js';
import { active_reaction, get } from '../internal/client/runtime.js';
import { active_reaction, get, onupdated } from '../internal/client/runtime.js';
import { increment } from './utils.js';
import { teardown } from '../internal/client/reactivity/effects.js';
@ -63,9 +63,10 @@ export class SvelteSet extends Set {
if (active_reaction !== null) {
this.#initial_reaction = active_reaction;
// since we only need `initial_reaction` as long as we are in a derived/effect we can
// safely create a teardown function that will reset it to null and allow for GC
teardown(() => {
onupdated(() => {
this.#initial_reaction = null;
});
}

Loading…
Cancel
Save