logo

useMotionValueEvent

useMotionValueEvent manages subscriptions to motion value store changes. It skips the initial synchronous emission that Svelte stores produce on subscribe, so the callback only fires on actual changes.

<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const x = useSpring(0)

  const unsub = useMotionValueEvent(x, 'change', (latest) => {
    console.log('x changed to', latest)
  })

  onDestroy(unsub)
</script>
<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const x = useSpring(0)

  const unsub = useMotionValueEvent(x, 'change', (latest) => {
    console.log('x changed to', latest)
  })

  onDestroy(unsub)
</script>

Usage

Import

<script>
  import { useMotionValueEvent } from '@humanspeak/svelte-motion'
</script>
<script>
  import { useMotionValueEvent } from '@humanspeak/svelte-motion'
</script>

Subscribe to changes

Pass a readable store, the event type 'change', and a callback:

<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const scale = useSpring(1)

  const unsub = useMotionValueEvent(scale, 'change', (latest) => {
    if (latest > 1.5) {
      console.log('Scale is large!')
    }
  })

  onDestroy(unsub)
</script>

<div
  style="transform: scale({$scale})"
  onpointerenter={() => scale.set(2)}
  onpointerleave={() => scale.set(1)}
>
  Hover me
</div>
<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const scale = useSpring(1)

  const unsub = useMotionValueEvent(scale, 'change', (latest) => {
    if (latest > 1.5) {
      console.log('Scale is large!')
    }
  })

  onDestroy(unsub)
</script>

<div
  style="transform: scale({$scale})"
  onpointerenter={() => scale.set(2)}
  onpointerleave={() => scale.set(1)}
>
  Hover me
</div>

Available events

EventDescription
'change'Fires whenever the store value updates (after the initial emission).

Cleanup

useMotionValueEvent returns an unsubscribe function. Call it inside onDestroy or at the end of an $effect:

<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const y = useSpring(0)

  // Option 1: onDestroy
  const unsub = useMotionValueEvent(y, 'change', (v) => console.log(v))
  onDestroy(unsub)
</script>
<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const y = useSpring(0)

  // Option 1: onDestroy
  const unsub = useMotionValueEvent(y, 'change', (v) => console.log(v))
  onDestroy(unsub)
</script>
<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'

  const y = useSpring(0)

  // Option 2: $effect cleanup
  $effect(() => {
    const unsub = useMotionValueEvent(y, 'change', (v) => console.log(v))
    return unsub
  })
</script>
<script>
  import { useMotionValueEvent, useSpring } from '@humanspeak/svelte-motion'

  const y = useSpring(0)

  // Option 2: $effect cleanup
  $effect(() => {
    const unsub = useMotionValueEvent(y, 'change', (v) => console.log(v))
    return unsub
  })
</script>

Advanced — raw subscribe

For full control you can use store.subscribe() directly. Note that Svelte stores fire the callback immediately with the current value on subscribe:

<script>
  import { useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const x = useSpring(0)

  // Fires immediately with current value, then on every change
  const unsub = x.subscribe((value) => {
    console.log('value:', value)
  })

  onDestroy(unsub)
</script>
<script>
  import { useSpring } from '@humanspeak/svelte-motion'
  import { onDestroy } from 'svelte'

  const x = useSpring(0)

  // Fires immediately with current value, then on every change
  const unsub = x.subscribe((value) => {
    console.log('value:', value)
  })

  onDestroy(unsub)
</script>

useMotionValueEvent is preferred when you only want to react to changes and not the initial value.

API Reference

Signature

useMotionValueEvent<T>(
  store: Readable<T>,
  event: 'change',
  callback: (latest: T) => void
): () => void
useMotionValueEvent<T>(
  store: Readable<T>,
  event: 'change',
  callback: (latest: T) => void
): () => void

Parameters

  • store Readable<T> — any Svelte readable store (e.g. useSpring, useTransform, useTime)
  • event 'change' — the event type to listen for
  • callback (latest: T) => void — invoked with the latest value on each change

Returns

() => void — an unsubscribe function that stops the subscription.

See also


Based on Motion’s useMotionValueEvent API.