paoloricciuti / sveltekit-search-params

The easiest way to read and WRITE from query parameters in sveltekit.
https://sveltekit-search-params.netlify.app
MIT License
497 stars 15 forks source link

Debouncing updates #10

Closed swyxio closed 1 year ago

swyxio commented 1 year ago

it can be nasty to the browser history when we type and the url bar is updated on every keystroke.

could we offer an easy way (probably not default, but recommended) to debounce the updates?

paoloricciuti commented 1 year ago

This could very well be an optional third parameter in the store creator.

What i'm thinking tho is that the url might still update with the replaceState option set to true and only after the debounce (which defaults to 0) we add a new history entry, we can even avoid to use sveltekit apis and just do a

history.pushState(history.state, null)

This is because i think is still important to update the url right away with every change but we can avoid filling the history by doing this. I think this would be the best in terms of UX.

The propsed api will look like this

<script>
    import {queryParam, ssp} from "sveltekit-search-params";

    const test = queryParam("test", ssp.string(), {
      debounceHistory: 300, //with this the URL will update on every keystroke but a new history will be debounced to 300ms
   })
</script>

<input bind:value={$test} />

We could even add another option to completely disable pushing history, something like

<script>
    import {queryParam, ssp} from "sveltekit-search-params";

    const test = queryParam("test", ssp.string(), {
       pushHistory: false, //no new history will be created for this query param
   })
</script>

<input bind:value={$test} />

The only thing i don't really like about this is that to pass the options you have to pass the encoder and decoder. I could put the options as an optional parameter in the second spot of the arguments but this would be a breaking change (it may still be worth given that we are still not at 1.0?).

Ideas on the API, the naming etc? I'll start to work on this tomorrow morning probably.

swyxio commented 1 year ago

i think this is a good API yes but i wonder if there is a lower level api we can offer that is less declarative but more generically powerful (maybe also replaces encoder?)

<script>
    import {queryParam, ssp, defaultEncoder} from "sveltekit-search-params";

    // assuming you have a standard debounce fn

    const test = queryParam("test", ssp.string(), (state, saveState) => {
      debounce(() => saveState(defaultEncoder(state)), 300)
   })
</script>

<input bind:value={$test} />

im not sure about the decoder equivalent but just giving some idea of alternative APIs that might be lower level but more powerful - i think these can sometimes be more useful/easier to maintain than pure declarative api's

paoloricciuti commented 1 year ago

I like the idea of a more powerful api but I dislike that this is the only option...what if we provide both? We could provide a set of options as the third argument and provide listener for the update:

<script>
    import {queryParam, ssp} from "sveltekit-search-params";

    const test = queryParam("test", ssp.string(), {
      debounceHistory: 300, //with this the URL will update on every keystroke but a new history will be debounced to 300ms
   })
   test.on("update", (state, saveState)=>{
        //Do your powerful stuff
   })
</script>

<input bind:value={$test} />
swyxio commented 1 year ago

up to you :) if in doubt, just do the simple thing first

paoloricciuti commented 1 year ago

Is just that I think the history issue is something very real and devs shouldn't be forced to write always the same code for something like this.

The idea of a callback in the "lifetime" is tempting tho

swyxio commented 1 year ago

yup yup. do whatever is simple to you, we dont need to overthink this, i was just offering the obvious alternative api

paoloricciuti commented 1 year ago

Yeah, I value your insight and I would love to build the best api possible that's why I was discussing with you. Thanks for the feedback, I'll work on this tomorrow

paoloricciuti commented 1 year ago

@sw-yx updated the package to 1.0.0 with the new options added. Let me know if it fits your needs.

I'll probably add the listener in another task.

swyxio commented 1 year ago

oh nice! thanks!