title: Svelte.js - How to rerender child components with new props?
body: <p>I am working on creating a multi-step form using Svelte.js but I've run into an issue rendering each form page with unique props.</p>
  
  <p>Here is a simple demo to show you what I mean:</p>
  
  <pre><code>// App.svelte
  
  &lt;script&gt;
      import FormPage from "./FormPage.svelte";
      let formNode;
  
      let pageSelected = 0;
  
      let formPages = [
          {
              name: "email",
              label: "Email"
          },
          {
              name: "password",
              label: "Password"
          }
      ];
  
      const handleIncPage = () =&gt; {
          if(pageSelected + 1 &lt; formPages.length)
          pageSelected = pageSelected + 1;        
      }
  
      const handleDecPage = () =&gt; {
          if(pageSelected -1 &gt; -1)
          pageSelected = pageSelected - 1;        
      }
  &lt;/script&gt;
  
  &lt;form bind:this={formNode}&gt;
      &lt;FormPage pageData={formPages[pageSelected]} /&gt;
  &lt;/form&gt;
  
  &lt;button on:click={handleDecPage}&gt;Back&lt;/button&gt;
  &lt;button on:click={handleIncPage}&gt;Next&lt;/button&gt;
  
  &lt;p&gt;
      Page Selected: {pageSelected}
  &lt;/p&gt;
  </code></pre>
  
  <p>And here's the <code>FormPage</code> component:</p>
  
  <pre><code>// FormPage.svelte
  
  &lt;script&gt;
      export let pageData;
  
      const {name, label} = pageData;
  &lt;/script&gt;
  
  &lt;div id={`form-page-${name}`}&gt;
      &lt;label&gt;Label: {label}&lt;/label&gt;
      &lt;input type="text" name={name} id={`input-${name}`} /&gt;
  &lt;/div&gt;
  
  &lt;pre&gt;{JSON.stringify(pageData, null, 2)}&lt;/pre&gt;
  </code></pre>
  
  <p>When I run the application and inc/dec <code>pageSelected</code>, the <code>pageData</code> prop changes successfully - as can be seen in the <code>pre</code> element. However, the <code>label</code> and <code>input</code> elements are exactly the same as they are on the first page. The <code>id</code> of the wrapping <code>div</code> element and the <code>id</code> of the <code>input</code> element are also unchanged.</p>
  
  <p>When I type into the <code>input</code> and change the page, the text remains the same.</p>
  
  <p>My goals are: to rerender the <code>FormPage</code> component when <code>pageSelected</code> changes and have the <code>input</code> and <code>label</code> change their values based on these new props. It should also be the case that when I change pages, the text already typed into the <code>input</code> should update and be empty (since no initial value is given to the inputs).</p>
  
  <p>Having done multi-step forms in React.js, I would use a unique <code>key</code> attribute to make sure my <code>FormPage</code> rerenders every time the <code>pageSelected</code> state changes. But I am unsure of how to do something similar in Svelte.js.</p>
  
  <p>Any suggestions?</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>Having read this <a href="https://stackoverflow.com/questions/57976936/howto-do-something-when-an-attribute-changes-in-svelte">question</a> on StackOverflow, I found out how to get the <code>input</code> and <code>label</code> elements to change as well as the <code>id</code> attributes. Here is my updated <code>FormPage</code> component:</p>
  
  <pre><code>// FormPage.svelte
  
  &lt;script&gt;
      export let pageData;
  
      $: name = pageData.name;
      $: label = pageData.label;
  
  &lt;/script&gt;
  
  &lt;div id={`form-page-${name}`}&gt;
      &lt;label&gt;Label: {label}&lt;/label&gt;
      &lt;input type="text" name={name} id={`input-${name}`}  /&gt;
  &lt;/div&gt;
  
  &lt;pre&gt;{JSON.stringify(pageData, null, 2)}&lt;/pre&gt;
  </code></pre>
  
  <p>However, the text inside the <code>input</code> still does not change.</p>
  
  <p>Is there a way to also update the value of the input as well? It would be ideal for my use case to create an entirely new element every time the props change, but it appears that Svelte is only updating the few attributes that have changed on the same underlying DOM node.</p>
  
  <p>Can Svelte be told to recreate elements in this circumstance?</p>
  
  <p><strong>UPDATE 2</strong></p>
  
  <p>So I have figured out a way to get the value of the input to change. Here is my updated <code>FormPage</code> component:</p>
  
  <pre><code>// FormPage.svelte
  
  &lt;script&gt;
      export let pageData;
  
          import {onMount, afterUpdate, onDestroy} from "svelte";
  
          let inputNode;
  
          $: name = pageData.name;
          $: label = pageData.label;
          $: value = pageData.initialValue || "";
  
          onMount(() =&gt; {
              console.log("Mounted");
          });
  
          afterUpdate(() =&gt; {
              console.log("Updated");
              inputNode.value = value
          });
  
          onDestroy(() =&gt; {
              console.log("Destroyed");
          });
  
  &lt;/script&gt;
  
  &lt;div id={`form-page-${name}`}&gt;
      &lt;label&gt;Label: {label}&lt;/label&gt;
      &lt;input type="text" name={name} id={`input-${name}`} bind:this={inputNode}  /&gt;
  &lt;/div&gt;
  
  &lt;pre&gt;{JSON.stringify(pageData, null, 2)}&lt;/pre&gt;
  </code></pre>
  
  <p>This solves the immediate problem of updating the input value.</p>
  
  <p>I've added the <code>onMount</code>, <code>afterUpdate</code> and <code>onDestroy</code> functions to see how the component changes over time. </p>
  
  <p>First, the <code>onDestroy</code> function is called, and then <code>onMount</code> after that. These both fire only once. However, <code>afterUpdate</code> fires every time the props change. This confirms my suspicion that the component wasn't being recreated.</p>