I'm using SvelteKit to build an app, and I import an external script (Apple's MapKit JS) in my app.html
like this:
<script src="https://cdn.apple-mapkit.com/mk/5.72.88/mapkit.js"></script>
I then have a Map.svelte
component that loads a point on a map using my own Airport
object. I have omitted extra details that aren't relevant with ...
:
// === Map.svelte ===
<script lang="ts">
import { onMount } from 'svelte'
import type { Airport } from '$lib/data/typesAirports'
export let airport:Airport
let mapWrap:HTMLDivElement
let map: mapkit.Map
onMount(() => {
setupMap(airport)
})
function setupMap(airport){
//Setup my mapkit object with my token
mapkit.init(...)
//Set my map instance
map = new mapkit.Map(mapWrap, {...})
//Create pin on map using airport latitude and longitude
const annotation = new mapkit.MarkerAnnotation(...airport latitude & longitude...)
map.addAnnotation(annotation)
}
</script>
<!-- Map in HTML -->
<div bind:this={mapWrap}></div>
So far, this works great. But when I change my airport
property in the parent component:
//=== Parent.svelte ===
<Map airport={airport} />
...there is no reactivity in the Map
component. My suspicion is this is because things that happen in onMount
are excluded from that reactivity, but I'm unclear on how that works.
If I try something like this, I get an error that airport
is undefined
:
$: setupMap(airport)
How can I preserve reactivity in a component like this that relies on an external JS library? Or more specifically, how do I get my map to reload when the airport
changes?
CodePudding user response:
onMount
happens once, when the component mounted to the DOM. The approach using a reactive statement is the correct one.
If a property can be uninitialized/undefined you can simply guard against that using an if
statement:
$: if (airport) setupMap(airport)
Regarding the loading of external scripts:
I would load them where they are used, ideally using a dynamic import()
; this only works for modules though. Imports like this can be awaited in async
functions or via the {#await}
directive. REPL example
For non-modules a <script>
tag can added dynamically and the load
event can be used to signal a component that the script can now be used. REPL example
A <link rel="prefetch" ...>
can be used to speed up the loading of these resources. (More on prefetching)