{"id":3341,"date":"2024-08-07T08:03:50","date_gmt":"2024-08-07T13:03:50","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=3341"},"modified":"2024-08-11T17:15:25","modified_gmt":"2024-08-11T22:15:25","slug":"snippets-in-svelte-5","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/snippets-in-svelte-5\/","title":{"rendered":"Snippets in Svelte 5"},"content":{"rendered":"\n<p>This post is the second in a 3-part series on Svelte 5.&nbsp;<a href=\"https:\/\/frontendmasters.com\/blog\/introducing-svelte-5\/\">Part one<\/a>&nbsp;was a basic introduction, covering nuts and bolts features like state, props, and effects. This post is all about snippets, an exciting new feature that allows for content reuse, and more importantly, injecting content into components you render.<\/p>\n\n\n<div class=\"box article-series\">\n  <header>\n    <h3 class=\"article-series-header\">Article Series<\/h3>\n  <\/header>\n  <div class=\"box-content\">\n            <ol>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/introducing-svelte-5\/\">Introducing Svelte 5<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/snippets-in-svelte-5\/\">Snippets in Svelte 5<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/fine-grained-reactivity-in-svelte-5\/\">Fine-Grained Reactivity in Svelte 5<\/a>\n            <\/li>\n                  <\/ol>\n        <\/div>\n<\/div>\n\n\n\n<p>If you&#8217;d like to see and experiment with the code in this post, <a href=\"https:\/\/github.com\/arackaf\/svelte-snippets\">see the GitHub repo<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-are-snippets\">What are snippets?<\/h2>\n\n\n\n<p>Snippets are a new feature in Svelte 5. They allow you to define, well&#8230; snippets of content. They&#8217;re&nbsp;<em>almost<\/em>&nbsp;lightweight components that you can find inside of a component file. Before you get too excited: they do not, as of now, allow you to define multiple components in one file. Snippets cannot be exported from anywhere, and even if they could, they do not allow you to define state. They are limited to props.<\/p>\n\n\n\n<p>They seem initially similar to React&#8217;s minimally useful Stateless Functional Components from back before hooks were a thing. But snippets also have a second use: they allow you to inject content into other components, and in so doing replace one of Svelte&#8217;s most awkward features: slots.<\/p>\n\n\n\n<p>Let&#8217;s see how.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"defining-snippets\">Defining snippets<\/h2>\n\n\n\n<p>We define snippets with the <code>#snippet<\/code> directive. The simplest snippet imaginable looks like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#snippet helloWorld()}\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>Hello World<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n{\/snippet}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>That defines the snippet. To render the snippet, we use the&nbsp;<code>@render<\/code>&nbsp;directive, like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">{@render helloWorld()}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you might have guessed, snippets can also receive props, or really, parameters, since snippets are more of a function, than a component. Parameters are listed in the parens, with types if you&#8217;re using TypeScript.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#snippet productDisplay(p: Product)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{p.url}\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"product url\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{p.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>${p.price.toFixed(2)}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Snippets can render other snippets<\/h3>\n\n\n\n<p>For example, this simple snippet&#8230;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#snippet productReview(review: Review)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>{review.date}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>{review.content}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>&#8230; can be used in this bigger snippet:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#snippet productDisplay(p: Product)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{p.url}\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"product url\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{p.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>${p.price.toFixed(2)}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>Reviews:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    {#each p.reviews ?? &#91;] as review}\n      {@render productReview(review)}\n    {\/each}\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then you can reuse that <code>productDisplay<\/code> snippet with different products in your component. Let&#8217;s see a minimal, full example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"ts\"<\/span>&gt;<\/span><span class=\"javascript\">\n  type Review = {\n    <span class=\"hljs-attr\">date<\/span>: string;\n    content: string;\n  };\n  type Product = {\n    <span class=\"hljs-attr\">name<\/span>: string;\n    url: string;\n    price: number;\n    reviews?: Review&#91;];\n  };\n\n  <span class=\"hljs-keyword\">let<\/span> searchedBook = $state&lt;Product&gt;({\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">\"Effective TypeScript: 83 Specific Ways to Improve Your TypeScript, 2nd Edition\"<\/span>,\n    <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">\"https:\/\/m.media-amazon.com\/images\/I\/71eWL4AqPqL._SL1500_.jpg\"<\/span>,\n    <span class=\"hljs-attr\">price<\/span>: <span class=\"hljs-number\">44.99<\/span>,\n    <span class=\"hljs-attr\">reviews<\/span>: &#91;\n      { <span class=\"hljs-attr\">date<\/span>: <span class=\"hljs-string\">\"2\/14\/2024\"<\/span>, <span class=\"hljs-attr\">content<\/span>: <span class=\"hljs-string\">\"Absolutely loved this book\"<\/span> },\n      { <span class=\"hljs-attr\">date<\/span>: <span class=\"hljs-string\">\"6\/2\/2024\"<\/span>, <span class=\"hljs-attr\">content<\/span>: <span class=\"hljs-string\">\"Even better than the first edition\"<\/span> },\n    ],\n  });\n  <span class=\"hljs-keyword\">let<\/span> relatedProduct = $state&lt;Product&gt;({\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">\"Modern C++ Design: Generic Programming and Design Patterns Applied\"<\/span>,\n    <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">\"https:\/\/m.media-amazon.com\/images\/I\/914ncVx1hxL._SL1413_.jpg\"<\/span>,\n    <span class=\"hljs-attr\">price<\/span>: <span class=\"hljs-number\">55.49<\/span>,\n  });\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n\n{#snippet productReview(review: Review)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>{review.date}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>{review.content}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}\n\n{#snippet productDisplay(p: Product)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{p.url}\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"product url\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{p.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>${p.price.toFixed(2)}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>Reviews:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>{#each p.reviews ?? &#91;] as review} {@render productReview(review)} {\/each}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Product Display Page<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n\n  {@render productDisplay(searchedBook)}\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">aside<\/span>&gt;<\/span>You might also be interested in:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">aside<\/span>&gt;<\/span>\n\n  {@render productDisplay(relatedProduct)}\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If that was the extent of Snippets they&#8217;d be a marginally useful convenience for re-using small bits of markup within a single component.<\/p>\n\n\n\n<p>But the main benefit of snippets is for <strong>injecting content into components<\/strong>. Previously, if you wanted to pass content into a component you&#8217;d use slots. Slots were always an awkward feature of Svelte, but they&#8217;re now deprecated in Svelte 5. We won&#8217;t cover them here, so check out&nbsp;<a href=\"https:\/\/svelte.dev\/docs\/special-elements#slot\">the docs<\/a>&nbsp;if you&#8217;re curious.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"passing-snippets-to-components\">Passing snippets to components<\/h2>\n\n\n\n<p>Snippets shine brightest when we pass them into other components. Let&#8217;s imagine a (grossly simplified)&nbsp;<code>DisplayProduct<\/code>&nbsp;page. It takes in a product, an optional related product, and a snippet to display a single product. This component will also render content in the header, which we&#8217;ll also pass in as a snippet.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"ts\"<\/span>&gt;<\/span><span class=\"javascript\">\n  <span class=\"hljs-keyword\">import<\/span> type { Snippet } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"svelte\"<\/span>;\n  <span class=\"hljs-keyword\">import<\/span> type { Product } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/types\"<\/span>;\n\n  type Props = {\n    <span class=\"hljs-attr\">product<\/span>: Product;\n    relatedProduct?: Product;\n    productDisplay: Snippet&lt;&#91;Product]&gt;;\n    children: Snippet;\n  };\n\n  <span class=\"hljs-keyword\">let<\/span> { product, relatedProduct, productDisplay, children }: Props = $props();\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n  {@render children()}\n  {@render productDisplay(product)}\n  \n  {#if relatedProduct}\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">aside<\/span>&gt;<\/span>You might also be interested in:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">aside<\/span>&gt;<\/span>\n    {@render productDisplay(relatedProduct)}\n  {\/if}\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>There&#8217;s a&nbsp;<code>Snippet<\/code>&nbsp;type that Svelte exports for us, so we can type the snippets we&#8217;re receiving. Specifying the parameters that a snippet receives is a little weird, because of how TypeScript is: we list the argumentes as a Tuple. So our <code>productDisplay<\/code> snippet will take a single argument that&#8217;s a <code>Product<\/code>.<\/p>\n\n\n\n<p>The snippet for showing the header I decided to name &#8220;children&#8221; which has some significance as we&#8217;ll see in a moment.<\/p>\n\n\n\n<p>Let&#8217;s put this component to use:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#snippet productDisplay(p: Product)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{p.url}\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"Image of product\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{p.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>${p.price.toFixed(2)}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">DisplayProduct<\/span> <span class=\"hljs-attr\">product<\/span>=<span class=\"hljs-string\">\"{searchedBook}\"<\/span> <span class=\"hljs-attr\">relatedProduct<\/span>=<span class=\"hljs-string\">\"{recommendedBook}\"<\/span> {<span class=\"hljs-attr\">productDisplay<\/span>}&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Product Display Page<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">DisplayProduct<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We&#8217;re passing the&nbsp;<code>productDisplay<\/code>&nbsp;snippet in for the&nbsp;<code>productDisplay<\/code>&nbsp;prop. Little note: Svelte allows you to write <code>{a}<\/code> instead of <code>a={a}<\/code> as a convenient shortcut.<\/p>\n\n\n\n<p>But notice the content we put directly inside of the&nbsp;<code>DisplayProduct<\/code>&nbsp;tags. If the component has a prop called&nbsp;<code>children<\/code>&nbsp;that&#8217;s a snippet, this content will be passed as that snippet. This is a special case just for props called children (similar to the children prop in React). You don&#8217;t&nbsp;<em>have<\/em>&nbsp;to do this; you&#8217;re free to manually pass a&nbsp;<code>children<\/code>&nbsp;prop, just like we did for&nbsp;<code>productDisplay<\/code>&nbsp;if you really want to.<\/p>\n\n\n\n<p>Let&#8217;s take a look at one more authoring convenience Svelte 5 gives us. If we&#8217;re just defining a snippet to be passed one time, to one component, Svelte lets us clean the syntax up a bit, like so:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">DisplayProduct<\/span> <span class=\"hljs-attr\">product<\/span>=<span class=\"hljs-string\">\"{searchedBook}\"<\/span> <span class=\"hljs-attr\">relatedProduct<\/span>=<span class=\"hljs-string\">\"{recommendedBook}\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Product Display Page<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n  {#snippet productDisplay(p: Product)}\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{p.url}\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"product url\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{p.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>${p.price.toFixed(2)}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  {\/snippet}\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">DisplayProduct<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As before, we have our&nbsp;<code>&lt;h1&gt;<\/code>&nbsp;content directly inside of the tags, as children. But we&#8217;ve also defined a snippet inside of those tags. This is a nice shorthand for passing a snippet as a prop (with the same name) to our component. Don&#8217;t worry, if the name you give this inline snippet doesn&#8217;t match a prop, TypeScript will tell you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"default-content-with-snippets\">Default Content with Snippets<\/h2>\n\n\n\n<p>One nice feature with slots is that you could define default content pretty easily.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">slot<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"header-content\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>Default content<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">slot<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Snippets don&#8217;t quite have anything like this built in, but they&#8217;re a flexible enough primitive that you really don&#8217;t need it.<\/p>\n\n\n\n<p>Let&#8217;s see how we can provide our own default content for when a Snippet is <em>not<\/em> passed in. As before let&#8217;s say we have our&nbsp;<code>DisplayProduct<\/code>&nbsp;component, except now our <code>productDisplay<\/code> and <code>children<\/code> snippets are optional<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">type Props = {\n  product: Product;\n  relatedProduct?: Product;\n  productDisplay?: Snippet<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">&#91;Product]<\/span>&gt;<\/span>;\n  children?: Snippet;\n};\n\nlet { product, relatedProduct, productDisplay, children }: Props = $props();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We have a few straightforward options for falling back to our own default content. We can simply test if we have a value for the snippet right in our template, and render the fallback if not.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#if children}\n  {@render children()} \n{:else}\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Fallback content<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n{\/if}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Or, we can set up our fallback right in our script:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">let<\/span> productDisplaySnippetToUse: Snippet&lt;&#91;Product]&gt; = productDisplay ?? productDisplayFallback;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">{#snippet productDisplayFallback(p: Product)}\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"{p.url}\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"product url\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{p.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n{\/snippet}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then we render that:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">{@render productDisplaySnippetToUse(product)}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"parting-thoughts\">Parting thoughts<\/h2>\n\n\n\n<p>Svelte 5 is an exciting release. This post turned to one of the more interesting new features: snippets, useful for injecting content into components, and for re-using small bits of content within a single component.<\/p>\n\n\n\n<p>Out with slots, in with snippets.<\/p>\n\n\n<div class=\"box article-series\">\n  <header>\n    <h3 class=\"article-series-header\">Article Series<\/h3>\n  <\/header>\n  <div class=\"box-content\">\n            <ol>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/introducing-svelte-5\/\">Introducing Svelte 5<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/snippets-in-svelte-5\/\">Snippets in Svelte 5<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/fine-grained-reactivity-in-svelte-5\/\">Fine-Grained Reactivity in Svelte 5<\/a>\n            <\/li>\n                  <\/ol>\n        <\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Out with slots, in with snippets.<\/p>\n","protected":false},"author":21,"featured_media":3091,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[161],"class_list":["post-3341","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-svelte"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-18-at-3.03.18%E2%80%AFPM.png?fit=1890%2C1122&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3341","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=3341"}],"version-history":[{"count":16,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3341\/revisions"}],"predecessor-version":[{"id":3443,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3341\/revisions\/3443"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/3091"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=3341"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=3341"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=3341"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}