Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restart or re-init component in Svelte

Is there an easy way to force a restart of Svelte components in place?

Restart use cases:

  • Clear file list of HTML files input (you cannot reset the path / value)
  • Nav bar dropdown collapse after item selection when using CSS hover

Maybe there are other solutions besides the restart, but lets use a component restart here.

Below the restart code which works fine for the upload use case:

SomeApp.svelte

<script>
      ...
      import Upload from "./upload/Upload.svelte";

      export let uid;  // firebase uid from auth

      // restart the Upload component after the upload 
      // to clear the filename of the <input type="file" ..../>  
      // restart by making use of a dynamic (falsy) component
      let upload_component = Upload;
      let restart = false;

      $: if (restart) {
         // use a falsy to stop / destroy this component 
         upload_component = null;
         // use a timer to queue a restart after the component has stopped
         setTimeout(() => {
           console.log('Upload component restarts')
           upload_component = Upload
         }, 0);
         console.log('Upload component restart queued');
         restart = false;  
      };

      ...
</script>


<!-- dynamic upload to restart the component when finished-->
<svelte:component uid={uid} this={upload_component} bind:finished={restart}/>

Upload.svelte

<script>
    import { onDestroy } from 'svelte';
    import { uploadCsv } from './upload.js'

    export let uid = null;
    export let finished;

    function uploadCsvCallback(result) {
      console.log(result);
      finished = true;
    };

    onDestroy(() => {
      console.log('Upload component destroyed');
    });
</script>

<style>
     .float-right {
          float: right;
      }
</style>

<!-- Select a CSV file to batch import a Firestore collection -->
<input
    type="file" name="files" class="float-right" accept=".csv" 
    on:change={uploadCsv(uid, uploadCsvCallback)}
/>

Update:
A component gets destroyed if the components is not rendered. So you can stop and restart a component when you toggle an if block arround a component.

Example:
1. toggle run from true to false to destroy the Upload component
2. and toggle run from false to true to restart the Upload component

{#if run}
  <Upload .....>
{/if}

And you can use a timer to toggle the restart.

run = true:
function restartComponent() {
  restart = false;  // stop / destroy
  setTimeout(() => run = true, 0); // and queue a restart
}
like image 921
voscausa Avatar asked Sep 29 '19 08:09

voscausa


People also ask

What is $$ in Svelte?

$$props references all props that are passed to a component, including ones that are not declared with export . It is not generally recommended, as it is difficult for Svelte to optimise. But it can be useful in rare cases – for example, when you don't know at compile time what props might be passed to a component.

Does Svelte use components?

In Svelte, an application is composed from one or more components. A component is a reusable, self-contained block of code that encapsulates HTML, CSS, and JavaScript that belong together, written into a . svelte file.

What is Prop Svelte?

In any real application, you'll need to pass data from one component down to its children. To do that, we need to declare properties, generally shortened to 'props'. In Svelte, we do that with the export keyword.


1 Answers

Yes, using a {#key} block:

<script>
import YourComponent from "./YourComponent.svelte"

let unique = {}

function restart() {
  unique = {} // every {} is unique, {} === {} evaluates to false
}
</script>

{#key unique}
  <YourComponent />
{/key}

<button on:click={restart}>Restart</button>

REPL

{#key} was introduced in Svelte v3.28, before that you needed to use a keyed {#each} block with only one item

like image 122
Bob Fanger Avatar answered Nov 16 '22 04:11

Bob Fanger