swyxio / swyxkit

An opinionated blog starter for SvelteKit + Tailwind + Netlify. Refreshed for SvelteKit 1.0!
https://swyxkit.netlify.app/
MIT License
681 stars 89 forks source link

The URL as State Manager #141

Closed swyxio closed 1 year ago

swyxio commented 1 year ago

category: essay tags: url, state, svelte, stores

One of the most common pain points cited by developers in the annual StateOfJS survey (now open! take it!) is "state management". Usually accessing state from various parts of the app, but also sending it over the wire for server rendering or for syncing it with other users (and, at scale, performantly updating relevant parts of the app when state changes).

For small usecases, a mechanism for that exists: the humble URL! specifically, the humble URLSearchParam.

When you serialize state to your URL, you can simply copy and paste your url bar to a coworker, who can then navigate directly to what you are seeing, with every text field and filter set exactly how you had it. It's basically an ultra flexible "direct link" for your app state. It's a magical experience when implemented well, and horribly frustrating when some parts of state are serialized but others are not.

Aside: this insight isnt just limited to the URLSearchParam; any frontend router essentially takes over the entire URL as a state manager - when you navigate to a new page, the URL updates clientside and the router updates its internal state accordingly. Just for some weird reason, routers typically stop at parsing/setting the search/query param when it is incredibly useful for sharing/serializing app state.

I suspect the reason that more people don't use URLSearchParams for state management is because the API is pretty low level:

Fortunately, https://github.com/paoloricciuti/sveltekit-search-params now handles that as a single Svelte Store, making it dead easy to set and get searchParams, define default values, and trusting that everything else from type safety to SSR-friendliness is all done for you.

The basic API we want:

<script lang="ts">
    import { queryParameters } from "sveltekit-search-params";

    const store = queryParameters();
</script>

<pre>
    {JSON.stringify($store, null, 2)}
</pre>
The count is {$store.count}
<input bind:value={$store.count} type="number"/>

sveltekit-search-params was implemented in swyxkit in https://github.com/sw-yx/swyxkit/pull/140/. You can see the amount of custom, hacky, untested code it replaces. Thanks to @paoloricciuti for the PR!

{% twitter https://twitter.com/PaoloRicciuti/status/1597889778384793602?s=20&t=OqvWkcbpn05Qil987cUTdQ %}

paoloricciuti commented 1 year ago

Thank you for the amazing work around the svelte community...glad this can help you and many others.

P.s. Imho a much more clear api is the one exported with the queryParam function

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

    const count = queryParameters("count", ssp.number(0));
</script>

The count is {$count}
<input bind:value={$count} type="number"/>
swyxio commented 1 year ago

yes i saw that in the docs!