Skip to content
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

Svelte 5 Infinite Effect / Reactive Loop #484

Open
pingu-codes opened this issue Nov 19, 2024 · 10 comments
Open

Svelte 5 Infinite Effect / Reactive Loop #484

pingu-codes opened this issue Nov 19, 2024 · 10 comments

Comments

@pingu-codes
Copy link
Contributor

Using svelte 5 with unovis causes an infinite reactive loop if more than 1 x/y component is rendered. The cause of this is the component action set within the xy container context:

setContext('component', () => ({
		update: (c: XYComponentCore<Datum>) => {
			config.components = [...config.components, c];
		},
		destroy: () => {
			config.components = config.components.filter((c) => !c.isDestroyed());
		}
	}));

Due to svelte 5's deeper reactivity the update function is called when data is added to one of the child line components, as a result of this the config.components pushes a duplicate component to config.components and an infinite loop begins and pushes duplicates to config.components.

A fix for this is simply preventing the update function from writing duplicates to config.components

setContext('component', () => ({
		update: (c: XYComponentCore<Datum>) => {
			if (config.components?.some((e) => e === c)) {
				return;
			}

			config.components = [...config.components, c];
		},
		destroy: () => {
			config.components = config.components.filter((c) => !c.isDestroyed());
		}
	}));
@rokotyan
Copy link
Contributor

@pingu-codes Thanks for figuring out the problem; we really appreciate it! We'll try it out soon and release a new version.

@lee00678
Copy link
Collaborator

@pingu-codes Thanks for the suggestion. I just released 1.5.0-beta.1 with your suggested fix. The browser renders a lot faster now, but I'm still seeing the infinite loop issue when using axis and annotations (I tried it with most of our existing components, others seem to be working. Here's the branch I used to publish 1.5.0-beta.1: qian/svelte-bug-fix. Any suggestions?

@pingu-codes
Copy link
Contributor Author

Hey @lee00678, it looks like it's largely the same problem for all of them, I suspect it's the same for all the components with separate lifetime actions. I'm not very familiar with the inner workings of @unovis/ts but for the axis specifically something within chart?.updateContainer({ ...config, ...($$restProps as XYContainerConfigInterface<Datum>) }); is causing the update action to be recalled. From my testing adding code like the following should fix the reactivity loop

if (config[`${e.__type__}Axis`] === c)
    return;
}
// ...

if (config.crosshair === c) {
    return;
}

@pingu-codes
Copy link
Contributor Author

After some testing... this kills the reactivity of the graph when the data changes.

@pingu-codes
Copy link
Contributor Author

pingu-codes commented Nov 20, 2024

Ok, took a longer look this morning. I believe the fixes I suggested are correct. The reason the graphs no longer rerender when the data changes is the chart?.updateContainer reactive statement is no longer triggered, I have no idea why but it can easily be fixed by doing this $: chart?.setData(data, true), (config.components = config.components); which will trigger the reactive statement and rerender the graph. I'm sure there's other options but this seems to work well, it's hard to tell what's changed to no longer trigger the reactivity correctly in svelte 5. I'm sure if you switched to svelte 5s runes it would be slightly easier to trace. But that being said other libraries seem to be following the path of ensuring their current code is compatible with svelte 5 and then waiting for svelte 6 before dedicating to the new rune system which makes the most sense IMO :)

@lee00678
Copy link
Collaborator

@pingu-codes Thanks for the update! I will give it a try today and keep you informed.

@lee00678
Copy link
Collaborator

@pingu-codes @rokotyan Just released 1.5.0-beta.3 with suggested fix. I've pushed the changes to my branch as well. qian/svelte-bug-fix. Did some quick testing, seems everything is working! Please feel free to test and let me know if there is anything I missed.

@pingu-codes once again, thanks for your contribution. If you want to submit a PR for all the above suggested changes so we can credit you, feel free to do so!

@pingu-codes
Copy link
Contributor Author

Is it ok if I grab your branch and copy over the commits so that I get the versioning and styling correct without worrying about it :)

@lee00678
Copy link
Collaborator

Is it ok if I grab your branch and copy over the commits so that I get the versioning and styling correct without worrying about it :)

Yea, definitely.

@pingu-codes
Copy link
Contributor Author

I've opened up the PR #487 👍

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

3 participants