If we have something like a Tooltip
class that needs to instantiate an instance, update that instance, and destroy that instance in sync with when the component is mounted, updated, and destroyed (as demonstrated in the code below), there seems to be two patterns for doing this.
- Using
use:action
- Using
onMount
andonDestroy
The use:action
method seems cleaner, but aside from that, are there any underlying differences between these two methods that would make one preferred over the other in certain situations?
Example of using use:action
:
<script>
import Tooltip from './tooltip'
export let text = ''
function initTooltip(node, text) {
const tooltip = Tooltip(node)
tooltip.text = text
return {
update(text) {
tooltip.text = text
},
destroy() {
tooltip.destroy()
}
}
}
</script>
<div use:initTooltip={text}>
<slot></slot>
</div>
Example of using onMount
and onDestroy
:
<script>
import Tooltip from './tooltip'
import { onMount, onDestroy } from 'svelte'
export let text = ''
let node
let tooltip
onMount(() => {
tooltip = Tooltip(node)
tooltip.text = text
})
$: if (tooltip && tooltip.text !== text) {
tooltip.text = text
}
onDestroy(() => {
if (tooltip) {
tooltip.destroy()
}
})
</script>
<div bind:this={node}>
<slot></slot>
</div>
If we have something like a Tooltip
class that needs to instantiate an instance, update that instance, and destroy that instance in sync with when the component is mounted, updated, and destroyed (as demonstrated in the code below), there seems to be two patterns for doing this.
- Using
use:action
- Using
onMount
andonDestroy
The use:action
method seems cleaner, but aside from that, are there any underlying differences between these two methods that would make one preferred over the other in certain situations?
Example of using use:action
:
<script>
import Tooltip from './tooltip'
export let text = ''
function initTooltip(node, text) {
const tooltip = Tooltip(node)
tooltip.text = text
return {
update(text) {
tooltip.text = text
},
destroy() {
tooltip.destroy()
}
}
}
</script>
<div use:initTooltip={text}>
<slot></slot>
</div>
Example of using onMount
and onDestroy
:
<script>
import Tooltip from './tooltip'
import { onMount, onDestroy } from 'svelte'
export let text = ''
let node
let tooltip
onMount(() => {
tooltip = Tooltip(node)
tooltip.text = text
})
$: if (tooltip && tooltip.text !== text) {
tooltip.text = text
}
onDestroy(() => {
if (tooltip) {
tooltip.destroy()
}
})
</script>
<div bind:this={node}>
<slot></slot>
</div>
Share
Improve this question
asked Sep 23, 2019 at 19:19
Elliot WaiteElliot Waite
1482 silver badges8 bronze badges
2
|
1 Answer
Reset to default 24If it's behaviour that you can imagine needing to reuse among multiple components, or if it's something that you can imagine applying to an element inside an {#if ...}
block (for example), then it probably belongs in an action.
It it's something that 'belongs' to the component itself, rather than a specific element, then it's probably more of a lifecycle thing.
In this case, my tendency would probably be to use an action.
Tooltip
is a class in a js file. CallingTooltip(node)
will attach some event listeners to that node and return an instance that has a.destroy()
method, that when called, removes those event listeners. – Elliot Waite Commented Sep 25, 2019 at 22:23