Here's the link to repro (Svelte Playground).
The problem is that when you add a "waypoint" and toggle the checkbox to enable its bearings (thus changing the respective nested object's enabled
property), Svelte won't see these changes. I can see that because the effect on the lines 41-44 won't log anything. If I use $inpsect
instead, there's also nothing.
let { directions, configuration } = {directions: {waypointsBearings: [], configuration: {bearings: true}}, on: () => {}, configuration: {}}
// @ts-expect-error It's safe to read the plugin's protected properties here.
if (!directions.configuration.bearings) {
console.warn("The Bearings Control is used, but the `bearings` configuration option is not enabled!");
}
function addWaypoint() {
directions.waypointsBearings.push({enabled: false})
onWaypointsChanged()
}
let waypointsBearings: {
enabled: boolean;
angle: number;
degrees: number;
}[] = $state([]);
// directions.on("addwaypoint", onWaypointsChanged);
// directions.on("removewaypoint", onWaypointsChanged);
// directions.on("movewaypoint", onWaypointsChanged);
// directions.on("setwaypoints", onWaypointsChanged);
function onWaypointsChanged() {
waypointsBearings = directions.waypointsBearings.map((waypointBearing, index) => {
if (waypointsBearings[index]) return waypointsBearings[index];
return {
enabled: configuration.defaultEnabled || !!waypointBearing,
angle: waypointBearing ? waypointBearing[0] : configuration.angleDefault,
degrees: waypointBearing
? waypointBearing[1]
: configuration.fixedDegrees
? configuration.fixedDegrees
: configuration.degreesDefault,
};
});
}
$effect(() => {
console.log("PIA");
console.log(waypointsBearings);
});
onWaypointsChanged();
(The addWaypoint
function is artifical and serves to replace the commented-out directions.on
calls. It's here just to replace the real map and its interactivity).
<button onclick={addWaypoint}>Add</button>
<div class="bearings-control {configuration.class}" style="display: {waypointsBearings.length ? 'block' : 'none'}">
<div class="bearings-control__list">
{#each waypointsBearings as waypointBearing, i}
<div
class="
bearings-control__list-item
{waypointBearing.enabled ? 'bearings-control__list-item--enabled' : 'bearings-control__list-item--disabled'}
"
>
<span class="bearings-control__number">{i + 1}. </span>
<input type="checkbox" bind:checked={waypointBearing.enabled} class="bearings-control__checkbox" />
I assume that this absence of reactivity for the inner objects is just a part of the broader issue (see the context below), but should be enough to start.
Here's some broader context for the problem. I have a working code (Svelte 4) which I'm trying to rewrite to Svelte 5. You can see the working Svelte 4 code here and you can see it in action (see that it actually works fine) here (try clicking the map to add waypoints, so that the "bearings" bar appears).
The changes apply as expected.
See the warning you get when logging state:
[svelte] console_log_state Your
console.log
contained$state
proxies. Consider using$inspect(...)
or$state.snapshot(...)
instead
https://svelte.dev/e/console_log_state
Changes to $state
do not affect the initial object, they are recorded on top of it via a Proxy
. If you want to get the current value of the state, take a $state.snapshot()
. If you only want to observe the values during debugging, use $inspect
.