I have this Svelte code:
Player.svelte:
<script> import PlayerControls from './PlayerControls.svelte'; let audio; </script> <audio src={...} bind:this={audio} /> <PlayerControls {audio} />
PlayerControls.svelte:
<script> import PlayIcon from '../icons/PlayIcon.svelte'; import PauseIcon from '../icons/PauseIcon.svelte'; export let audio; const onClick = () => { if (audio?.paused) audio.play(); else audio.pause(); }; </script> {#if audio?.paused} <PlayIcon {onClick} /> {:else} <PauseIcon {onClick} /> {/if}
If I press the play icon, the icon does not change, but the audio starts, if I click again, the audio stops, but the icon does not change. It seems that audio.paused only "changes" in the script, not in the html. What's the problem here, and what don't I understand about Svelte?
In your given case, the most robust solution is to utilize specific
<audio>
elements Events to alert svelte to recheck the status of the ref. This allows svelte to manage your listener lifecycle, and also allows the element itself to handle all edge cases of when/how the playback state changes.REPL
Original answer
The documentation link in my comment covers a simple solution to your problem Reactivity/Updating Arrays and Objects, which is to simply reassign
audio
asonClick
The last step in the handler.Keep in mind that this will not track changes in
paused
if the audio ends on its own.REPL
edit
I initially suggested changing the
paused
attribute directly:But ignores the fact that
audio
is aref
andpaused
is a read-only property.