svelte

How to update states inside await block in svelte5?


I have a form that basically upon clicking the form, it runs handleSubmit() whih basically which basically does

    if (verifyPassword === verifyConfirmPassword){
        register.setRegistrationStatus(true)

so when it is true it sends the credentials to my flask backend with sendRegistrationCredentials.

I am able to catch the error but issue is i cant change the state of register.isRegistrationSuccessful to false. this causes svelte to give this error

Uncaught (in promise) Svelte error: state_unsafe_mutation
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without \$state``

any help would be appreciated. heres the full code

    <form onsubmit = {(preventDefault(() => handleSubmit()))}>
        <Username bind:value={username}/>
        <Email  bind:value={email}/>
        <Password bind:value={password}/>
        <ConfirmPassword {password} bind:value={confirmPassword}/>

        {#if register.isRegistrationSuccessful}
            {#await sendRegistrationCredentials}
                <button class="btn btn-info mt-4 btn-disabled">Sign up <span class="loading loading-spinner loading-sm"></span></button>
            {:then}
                {goto('/check-mail')}
            {:catch error}
            <button class="btn btn-info mt-4">Sign up</button>
            <div class="mt-4"><span class="text-error">{error}</span></div>
            {register.isRegistrationSuccessful = false}
            {/await} 
        {:else}
        <button class="btn btn-info mt-4">Sign up</button>

        {/if}
    </form>

Solution

  • You should never modify state in the template.

    Either use event callbacks where appropriate (e.g. form submissions & button clicks) or use reactive logic in the <script>: For computed state $derived, for side effect logic $effect (though modifying $state inside $effect is generally discouraged; it can be hard to track and can lead to infinite loops if one is not careful).

    (In newer versions of Svelte 5 you can also overwrite $derived state later.)

    In scenarios like this, #await can usually be replaced by storing state (pending/result/error) in a variable and using #if/:else if chains in the template instead. The await logic itself is moved to an $effect or callback, where you can also update other state.