add invalidate fn

opaque-rune
Dominic Gannaway 9 months ago
parent 0166bc4850
commit abe01a76e9

@ -144,8 +144,8 @@ declare namespace $state {
* *
* @param initial The initial value * @param initial The initial value
*/ */
export function opaque<T>(initial: T): [T, () => void]; export function opaque<T>(initial: T): [T, (mutate?: (value: T) => void) => void];
export function opaque<T>(): [T | undefined, () => void]; export function opaque<T>(): [T | undefined, (mutate?: (value: T) => void) => void];
/** /**
* To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: * To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`:

@ -164,7 +164,13 @@ export function VariableDeclaration(node, context) {
b.declarator(state_id, b.call('$.opaque_state', value)), b.declarator(state_id, b.call('$.opaque_state', value)),
b.declarator( b.declarator(
invalidation_id, invalidation_id,
b.thunk(b.call('$.set', state_id, b.member(state_id, b.id('v')))) b.arrow(
[b.id('$$fn')],
b.sequence([
b.call(b.id('$$fn'), b.member(state_id, b.id('v'))),
b.call('$.set', state_id, b.member(state_id, b.id('v')))
])
)
) )
); );
continue; continue;

@ -98,7 +98,7 @@ export function VariableDeclaration(node, context) {
const invalidation_id = /** @type {Identifier} */ (pattern.elements[1]); const invalidation_id = /** @type {Identifier} */ (pattern.elements[1]);
declarations.push( declarations.push(
b.declarator(state_id, value), b.declarator(state_id, value),
b.declarator(invalidation_id, b.thunk(b.block([]))) b.declarator(invalidation_id, b.arrow([b.id('$$fn')], b.call(b.id('$$fn'), state_id)))
); );
continue; continue;
} }

@ -0,0 +1,13 @@
<script>
let { count } = $props();
let [obj, invalidate] = $state.opaque({ count: 0 });
$effect(() => {
invalidate((obj) => {
obj.count = count;
});
});
</script>
<p>{obj.count}</p>

@ -0,0 +1,18 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<p>0</p><button>+1</button>`,
test({ assert, target }) {
const button = target.querySelector('button');
button?.click();
flushSync();
assert.htmlEqual(target.innerHTML, `<p>1</p><button>+1</button>`);
button?.click();
flushSync();
assert.htmlEqual(target.innerHTML, `<p>2</p><button>+1</button>`);
}
});

@ -0,0 +1,8 @@
<script>
import Child from './Child.svelte';
let count = $state(0);
</script>
<Child {count} />
<button onclick={() => count += 1}>+1</button>

@ -2691,8 +2691,8 @@ declare namespace $state {
* *
* @param initial The initial value * @param initial The initial value
*/ */
export function opaque<T>(initial: T): [T, () => void]; export function opaque<T>(initial: T): [T, (mutate?: (value: T) => void) => void];
export function opaque<T>(): [T | undefined, () => void]; export function opaque<T>(): [T | undefined, (mutate?: (value: T) => void) => void];
/** /**
* To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: * To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`:

Loading…
Cancel
Save