Search code examples
sveltesvelte-3two-way-bindingsvelte-store

How to determine the cause of state update in svelte two way binding?


There's a variable x bound to an input element.

export let x;

$: doSomethingIfxWasUpdatedExternally();

<input bind:value={x} />

How to know whether the state x was updated externally or by the user typing in the input?


Solution

  • As far as I know, you can't. Instead of the binding, you could pass in the value in and use the input event to get it out.

    But even then, reactive statements can and will fire fairly unpredictably, you should not rely on when and how often they run. They should define invariants not run transactional logic.


    Here would be a convoluted set-up that sort of works, but I definitely would not recommend using this:

    <script>
        import { afterUpdate } from 'svelte';
    
        export let value;
    
        let updating = false;
        // Function hides `updating` from reactive statement
        const isUpdating = () => updating;
        // Reset flag after reactive statements
        afterUpdate(() => updating = false);
        
        $: if (isUpdating() == false) {
            console.log('Value changed externally:', value);
        }
    
        function onInput(e) {
            updating = true;
            value = e.target.value;
            console.log('Value changed internally:', e.target.value);
        }
    </script>
    
    <input {value} on:input={onInput} />
    

    REPL