{
  "$type": "site.standard.document",
  "content": {
    "$type": "at.markpub.markdown",
    "flavor": "gfm",
    "renderingRules": "markdown-it",
    "text": {
      "$type": "at.markpub.text",
      "markdown": "> 💡 This post will serve as a collection of ongoing notes.\n\n> 💡 [Read part 1 of this series on simpler shared runed state, derived state and more.](https://fubits.dev/notes/svelte-5-patterns-simple-shared-state-getcontext-tweened-stores-with-runes/)\n\n## General Learnings\n\nFrom studying the migration guide and current [GitHub issues](https://github.com/sveltejs/svelte/issues) for Svelte / Svelte 5 we learn that:\n\n- `actions` still exist (e.g. for [event modifiers](https://svelte.dev/docs/svelte/v5-migration-guide#Event-changes-Event-modifiers))\n- `tick` still exists\n- `event` handling is now more „native“\n  - write handler functions that accept an `event` object, and handle as intended in the [Event API](https://developer.mozilla.org/en-US/docs/Web/API/Event)\n  - this is even more important for event modifiers that relied on syntactic sugar like `event|preventDefault`\n  ```javascript\n  <script>\n   const handleEvent(e) => e.preventDefault()\n  </script>\n  \n  <button onclick={handleEvent} />\n  ```\n## Notes on JSDoc Types & IntelliSense\n\n- Reminder: there is a component annotation / documentation pattern with `@component`\n\n![Screenshot of a basic component docs example. @slot probably should be replaced with @image (snippet).](https://fubits.dev/_astro/svelte-5-jsdoc-component.d5OO9Wym_163T0a.webp)\n\n*Screenshot of a basic component docs example. @slot probably should be replaced with @image (snippet).*\n\n- unlike JSDoc typing, it must be within the markup / HTML section\n- **but** it seems you can just put it at the top of the file before the very first `<script>` tag:\n ```javascript\n <!--\n\t@component\n\t@slot default - The map container with image, vector, and text annotations\n\t-->\n <script>\n  import { getContext } from 'svelte'\n  import { fade } from 'svelte/transition'\n  // ...\n </script>\n \n <div>your markup</div>\n ```\n- TBC: if types can be defined / imported / exported here instead of within <script></script>\n\n- `JSDoc` types can be recycled - exported / imported - when defined in `<script module />` ([Maintainer comment](https://github.com/sveltejs/svelte/issues/13886#issuecomment-2437127953))\n  - define in one component\n ```javascript\n // $lib/ComponentA.svelte\n <script module>\n /** @typedef {\"myType\"} MyType */\n </script>\n \n <script>\n  // your logic\n </script>\n ```\n- import and recycle in another component\n ```javascript\n // $lib/ComponentB.svelte\n <script>\n   /** @import { MyType } from \"$lib/ComponentA.svelte\" */\n \n   /**\n    * @param {MyType} x\n    */\n   function stuff(x) {\n   \n   }\n </script>\n ```\n- you can even import in utility libraries / `.js` files (that probably includes `.svelte.js` files)\n ```javascript\n // $utils/+utils.js\n /** @import { MyType } from \"$lib/ComponentA.svelte\" */\n \n /**\n  * @param {MyType} x\n  */\n function stuff(x) {\n   \n }\n ```\n## Notes on `$effect`\n\n- `$effect` and `onMount` are not the same\n  - `onMount()`  is only run when the component is mounted.\n  - `$effect` is run when\n    - the component is mounted\n    - when any of the tracked dependencies are changed\n  - `$effect.pre` runs before changes are applied to the DOM\n- ~~_observation_: it’s unclear if `onMount` is supposed to be deprecated or not (probably a Svelte 6 thing)~~\n- `$effect` is not encouraged ([Docs](https://svelte.dev/docs/svelte/$effect#When-not-to-use-effects), [GitHub Issue by Core Maintainer](https://github.com/sveltejs/svelte/issues/10193), [Tweet by Core Maintainer](https://x.com/PaoloRicciuti/status/1851002697383629004))\n- `$effect` doesn’t run on the server\n  - `$derived` does\n- `$effect.once()` doesn’t exist yet (svelte@5.1.2), but can be simulated with\n ```javascript\n import { untrack } from 'svelte';\n \n $effect(() => {\n  untrack(async () => {\n   await fetch(\"/\");\n  })\n });\n ```\n- `async` within `$effect` is discouraged ([Maintainer](https://github.com/sveltejs/svelte/issues/13916#issuecomment-2437260734))\n- `async` within `onMount` is discouraged ([example](https://github.com/sveltejs/svelte/issues/13916#issuecomment-2437261977))\n\n## Notes on `$props()`\n\n- to only extract specific properties and collect the rest\n ```javascript\n let { foo, bar, ...rest } = $props();\n ```\n- to collect / preserve all properties: don’t destructure\n ```javascript\n let props = $props();\n ```\n- pass to child\n ```html\n <Button {...rest} />\n <Button {...props} />\n ``` ```javascript\n // Button.svelte\n <script>\n  let props = $props();\n </script>\n \n <button {...props}>\n  click me\n </button>\n ```\n- `$bindable` can have a default\n ```javascript\n let { item = $bindable(\"default\") } = $props()\n ```\n## Reactive Built-Ins: Set, Map, Date, URL, URLSearchParams with Svelte 5\n\n- these so called “built-ins” aren’t reactive off the shelf\n- instead, there’s a collection of reactive “built-ins” in  `svelte/reactivity` ([Docs](https://svelte.dev/docs/svelte/svelte-reactivity))\n\n> 💡 as of svelte@5.1.3:\n\n- `SvelteDate`\n- `SvelteMap`\n- `SvelteSet`\n- `SvelteURL`\n- `SvelteURLSearchParams`\n\n## TODO / WIP: Standalone modules / UMD / ES6 / IIFE with Vite & Svelte 5\n\n> 💡 if you don’t know what this means, what this Svelte Summit Talk by Jesse Skinner: [https://www.youtube.com/watch?v=uWxkaDdqfpI](https://www.youtube.com/watch?v=uWxkaDdqfpI)  \n>\n> TL;DR: Svelte is a compiler; you can compile Svelte components to regular standalone JavaScript modules and mount them wherever you can run JavaScript. You can even pass functions as props and expose component methods to the mounting scope.\n\n- in Svelte 5 components are functions - before, they were Classes (e.g. `new SvelteComponent()`)\n- mount with either `mount` or `hydrate`\n  - `hydrate` picks up server-rendered HTML\n  - you can preserve the CSS with a compiler option: `css: 'injected'`\n    - example: [github.com/fubits1/bun-svelte-ssr/commit/](https://github.com/fubits1/bun-svelte-ssr/commit/960ea759fd5481a4cab10b6e4d202200c0c5226b#diff-8387cced6f88ca3ed9b85e1246ace5cca9b27473645c0f00f32153035481df9cR16)\n  - options now include an `events: {eventType: callback()}` property\n  - ~~tbc:~~ ~~`$state`~~ ~~might be used in the instantiating scope~~\n    - only in .svelte / .svelte.js\n  - there’s `unmount` for destroying\n  - see working example for a server-side-rendered Svelte component using Bun and the Svelte compiler: [https://github.com/fubits1/bun-svelte-ssr](https://github.com/fubits1/bun-svelte-ssr)\n\n## What I don’t understand yet\n\n- `$state.snapshot`\n\n > 💡 why and how and what for?\n ```javascript\n $effect( () => {\n   // Get a snapshot :\n   const data = $state.snapshot(config);\n \n   // Save data\n   // ...\n   console.log(data);\n  });\n ```\n- level or granularity of shared / bindable reactivity ([example GitHub issue](https://github.com/sveltejs/svelte/issues/13914))\n- migration guide: „accessors option is ignored“\n\n > “Setting the accessors option to true makes properties of a component directly accessible on the component instance. In runes mode, properties are never accessible on the component instance. You can use component exports instead if you need to expose them.” ([Svelte 5 Migration Guide](https://svelte.dev/docs/svelte/v5-migration-guide#Breaking-changes-in-runes-mode-accessors-option-is-ignored))\n\n---\n\n> 💡 to be continued\n"
    }
  },
  "description": "More ongoing learnings and new patterns from working with Svelte 5.",
  "path": "/notes/svelte-5-patterns-props-effect-jsdoc-types-set-map-and-more/",
  "publishedAt": "2024-10-31T00:00:00.000Z",
  "site": "at://did:plc:6aglx53tojyuwxwueap5og3h/site.standard.publication/self",
  "tags": [
    "Svelte 5"
  ],
  "textContent": "💡 This post will serve as a collection of ongoing notes.\n\n💡 Read part 1 of this series on simpler shared runed state, derived state and more.\n\nGeneral Learnings\n\nFrom studying the migration guide and current GitHub issues for Svelte / Svelte 5 we learn that:\n\nactions still exist (e.g. for event modifiers)\ntick still exists\nevent handling is now more „native“\nwrite handler functions that accept an event object, and handle as intended in the Event API\nthis is even more important for event modifiers that relied on syntactic sugar like event|preventDefault\n\n<script>\nconst handleEvent(e) => e.preventDefault()\n</script>\n\n<button onclick={handleEvent} />\n\nNotes on JSDoc Types & IntelliSense\n\nReminder: there is a component annotation / documentation pattern with @component\n\nScreenshot of a basic component docs example. @slot probably should be replaced with @image (snippet).\n\nScreenshot of a basic component docs example. @slot probably should be replaced with @image (snippet).\n\nunlike JSDoc typing, it must be within the markup / HTML section\nbut it seems you can just put it at the top of the file before the very first <script> tag:\n\n<!--\n@component\n@slot default - The map container with image, vector, and text annotations\n-->\n<script>\nimport { getContext } from 'svelte'\nimport { fade } from 'svelte/transition'\n// ...\n</script>\n\n<div>your markup</div>\n\nTBC: if types can be defined / imported / exported here instead of within <script></script>\n\nJSDoc types can be recycled - exported / imported - when defined in <script module /> (Maintainer comment)\ndefine in one component\n\n// $lib/ComponentA.svelte\n<script module>\n/** @typedef {\"myType\"} MyType */\n</script>\n\n<script>\n// your logic\n</script>\n\nimport and recycle in another component\n\n// $lib/ComponentB.svelte\n<script>\n/** @import { MyType } from \"$lib/ComponentA.svelte\" */\n\n/**\n@param {MyType} x\n*/\nfunction stuff(x) {\n\n}\n</script>\n\nyou can even import in utility libraries / .js files (that probably includes .svelte.js files)\n\n// $utils/+utils.js\n/** @import { MyType } from \"$lib/ComponentA.svelte\" */\n\n/**\n@param {MyType} x\n*/\nfunction stuff(x) {\n\n}\n\nNotes on $effect\n\n$effect and onMount are not the same\nonMount() is only run when the component is mounted.\n$effect is run when\nthe component is mounted\nwhen any of the tracked dependencies are changed\n$effect.pre runs before changes are applied to the DOM\n_observation_: it’s unclear if onMount is supposed to be deprecated or not (probably a Svelte 6 thing)\n$effect is not encouraged (Docs, GitHub Issue by Core Maintainer, Tweet by Core Maintainer)\n$effect doesn’t run on the server\n$derived does\n$effect.once() doesn’t exist yet (svelte@5.1.2), but can be simulated with\n\nimport { untrack } from 'svelte';\n\n$effect(() => {\nuntrack(async () => {\nawait fetch(\"/\");\n})\n});\n\nasync within $effect is discouraged (Maintainer)\nasync within onMount is discouraged (example)\n\nNotes on $props()\n\nto only extract specific properties and collect the rest\n\nlet { foo, bar, ...rest } = $props();\n\nto collect / preserve all properties: don’t destructure\n\nlet props = $props();\n\npass to child\n\n<Button {...rest} />\n<Button {...props} />\n\n// Button.svelte\n<script>\nlet props = $props();\n</script>\n\n<button {...props}>\nclick me\n</button>\n\n$bindable can have a default\n\nlet { item = $bindable(\"default\") } = $props()\n\nReactive Built-Ins: Set, Map, Date, URL, URLSearchParams with Svelte 5\n\nthese so called “built-ins” aren’t reactive off the shelf\ninstead, there’s a collection of reactive “built-ins” in svelte/reactivity (Docs)\n\n💡 as of svelte@5.1.3:\n\nSvelteDate\nSvelteMap\nSvelteSet\nSvelteURL\nSvelteURLSearchParams\n\nTODO / WIP: Standalone modules / UMD / ES6 / IIFE with Vite & Svelte 5\n\n💡 if you don’t know what this means, what this Svelte Summit Talk by Jesse Skinner: https://www.youtube.com/watch?v=uWxkaDdqfpI\n\nTL;DR: Svelte is a compiler; you can compile Svelte components to regular standalone JavaScript modules and mount them wherever you can run JavaScript. You can even pass functions as props and expose component methods to the mounting scope.\n\nin Svelte 5 components are functions - before, they were Classes (e.g. new SvelteComponent())\nmount with either mount or hydrate\nhydrate picks up server-rendered HTML\nyou can preserve the CSS with a compiler option: css: 'injected'\nexample: github.com/fubits1/bun-svelte-ssr/commit/\noptions now include an events: {eventType: callback()} property\ntbc: $state might be used in the instantiating scope\nonly in .svelte / .svelte.js\nthere’s unmount for destroying\nsee working example for a server-side-rendered Svelte component using Bun and the Svelte compiler: https://github.com/fubits1/bun-svelte-ssr\n\nWhat I don’t understand yet\n\n$state.snapshot\n\n💡 why and how and what for?\n\n$effect( () => {\n// Get a snapshot :\nconst data = $state.snapshot(config);\n\n// Save data\n// ...\nconsole.log(data);\n});\n\nlevel or granularity of shared / bindable reactivity (example GitHub issue)\nmigration guide: „accessors option is ignored“\n\n“Setting the accessors option to true makes properties of a component directly accessible on the component instance. In runes mode, properties are never accessible on the component instance. You can use component exports instead if you need to expose them.” (Svelte 5 Migration Guide)\n\n💡 to be continued",
  "title": "Svelte 5 Patterns (Part 2): $props, $effect, JSDoc types, Set, Map, and more",
  "updatedAt": "2024-10-31T00:00:00.000Z"
}