Skip to content

use:svelteTime 的 action 会丢失对传入参数的响应性 #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Sincenir opened this issue Mar 27, 2025 · 6 comments
Open

use:svelteTime 的 action 会丢失对传入参数的响应性 #62

Sincenir opened this issue Mar 27, 2025 · 6 comments
Assignees

Comments

@Sincenir
Copy link

In svelteAction svelteTime, if the object is a state, state lost its reactivity, unlinke update in svelte4.

e.g.

<script>
	import { svelteTime } from 'svelte-time';
	let data = $state.raw({
		timestamp: '2021-02-02',
		format: 'dddd @ h:mm A · MMMM D, YYYY'
	});

	setTimeout(() => {
		data = {
			timestamp: '2025-04-02',
			format: 'dddd @ h:mm A · MMMM D, YYYY'
		};
	}, 3000);

	$effect(() => {
		console.log(data);
	});
</script>

<time use:svelteTime={data}></time>
@metonym
Copy link
Owner

metonym commented Mar 27, 2025

Hello, can you try the following:

  • Use $state instead of $state.raw (cannot be mutated)
  • Update the field timestamp on data directly
<script>
	import { svelteTime } from 'svelte-time';
	let data = $state({
		timestamp: '2021-02-02',
		format: 'dddd @ h:mm A · MMMM D, YYYY'
	});

	setTimeout(() => {
		data.timestamp = '2025-04-02'
	}, 3000);
</script>

<time use:svelteTime={data}></time>

@Sincenir
Copy link
Author

Thanks.

Yes, it's possible. But is there a solution to raw?

@Sincenir
Copy link
Author

Another way is to adjust the incoming data into a function and obtain the result through the function.

function svelteTime(dom: Element, getOption: () => data) {
$effect(() => {console.log(getOption())})
}

@metonym
Copy link
Owner

metonym commented Mar 27, 2025

I'll take a look at supporting the data parameter as a function.

@metonym metonym self-assigned this Mar 27, 2025
@Sincenir
Copy link
Author

Or can consider mixing svelte4 and svelte5.

function svelteTime(dom, op) {
    let internalOp = $state(op)
    $effect(() => {
        console.log(internalOp)
    })

    return {
        update(nOp) { internalOp = nOp}
    }
}

Bu it doesn't seem to be the best way.

@Sincenir
Copy link
Author

I'll take a look at supporting the data parameter as a function.

I used a relatively elegant way of writing, guaranteeing that the external parameters remain unchanged, and the internal use `() => data 'fetch. We can create a createEnhanceAction method, encapsulate the update internally, and discard the middle layer after svelte5 does new support.

function createEnhanceAction<T>(actionFn: (node: Element, getValue: () => T) => void) {
	return (node: Element, options: T) => {
		let internalOptions = $state<T>(options);

		actionFn(node, () => internalOptions);
		return {
			update(newOptions: T) {
				internalOptions = newOptions;
			},
		};
	};
}

function internalSvelteTime<T>(dom, getOp: () => T) {
    $effect(() => {
        console.log(getOp())
    })
}

const svelteTime = createEnhanceAction<any>(internalSvelteTime)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants