Hi,
I have a textbox to search a list of items to display, like so: https://svelte.technology/repl?version=1.40.2&gist=169f64277a48f68c7be50d3fc7bba3a7
The problem is, with very large lists, or more complex searches, each keystroke can slow the browser down while the computed property re-computes. I'd like a way to debounce the re-computation so that the user can type without browser slowdown on every keystroke.
I've worked around the issue by dropping the bind:value="..." and replacing it with on:input="...", where the event handler is a debounced function that sets the data: https://svelte.technology/repl?version=1.40.2&gist=aa2877e49eea3fd1ebc5ce78a910cc4e
The workaround doesn't feel like a 'proper' solution, though it does what I want it to do. The drawback is that the data-binding is gone, and any other methods that set the 'search' data will also have to update the textbox's value.
Would it be possible for the static analysis to allow wrapping the computed property methods? I imagine the code to look like this: https://svelte.technology/repl?version=1.40.2&gist=2cb2f49c906e0af49a21d0168f5021bf
I think this is the right thing to do:
<input type="text" bind:value="inputValue" />
oncreate () {
this.observe('inputValue', debounce((inputValue) => {
this.set({ search: inputValue })
}, 250))
},
I needed an example for 2019, and came up with:
<script>
let search = '';
let inputValue = '';
let searchQuery = ...;
let updateSearchDebounced = _.debounce(val => {search = val}, 250)
$: updateSearchDebounced(inputValue);
$: searchQuery.refetch({search});
let setInputValue = val => {inputValue = val};
$: setInputValue(search); // In case the search is updated other than through the input.
</script>
2020 version for Svelte 3.
This snippet is part of a larger feature that performs a deep search by file name partial, inside the current folder. The debounce prevents it from running the search on every keypress.
<script>
let searchStr = "";
let folderContents = [];
// Watch searchStr for changes and call expensive function getFolderContents
$: folderContents = getFolderContents('.', searchStr);
// debounce implementation of your choice; here it's similar to Lodash
const onInput = debounce(event => {
searchStr = event.target.value;
}, 250);
</script>
<input type="text" on:input={onInput} />
@breadthe It is not scalable. What if you want to compute something from 5, 6 inputs?
@vannhi agree - I was only concerned about a single input. For my use-case it works but more complex scenarios may not. I'm hoping debounce will get added to Svelte eventually.
Most helpful comment
I needed an example for 2019, and came up with: