Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Feature Request: Official Recommended Global Request Cache Pattern in Svelte #16434

Open
@mithi

Description

@mithi

Describe the problem

While building apps with Svelte 5, I’ve often run into the need to share and reuse the state of async requests (data, loading, error) across multiple components — similar to how React Query or SWR work in React.

As far as I know, there isn’t an official or idiomatic pattern in Svelte for implementing a global request cache. This often leads developers (myself included) to reinvent the wheel, usually borrowing patterns from React that don’t feel quite natural in Svelte.

I’m aware of TanStack Query for Svelte, but it seems to have several issues with Svelte 5 and doesn’t appear to be prioritized at the moment.

Below is my current approach. I suspect I’ve leaned too heavily on React-style patterns and that it is not idiomatic Svelte 5. I’m still very new to Svelte 5, so it’s possible I’m overcomplicating things — and I’d appreciate any guidance...

📐 Current Approach (Most likely wrong / an anti-pattern)

I maintain a global store:

typeGlobalRequestCacheStore=SvelteMap<string,RequestCache<StableKey,unknown>>;letglobalRequestCacheStore:GlobalRequestCacheStore|null=null;

It should be initialized at the root of the app with:

constglobalRequestCache=()=>{if(globalRequestCacheStore!=null){thrownewError('globalRequestCacheStore already exists');}globalRequestCacheStore=newSvelteMap();return()=>{globalRequestCacheStore=null;};};

The root component calls like this:

constdestroyCache=globalRequestCache();onDestroy(()=>destroyCache());

The store holds instances of class given a corresponding hash of the key.
(Below is a simplified version of the class implementation)

classRequestCache<KextendsStableKey,T>{  #state=$state<{data:T|null;error:Error|null;status:RequestStatus}>({data:null,error:null,status:'idle'});  #requestFn:RequestFn<K,T>;  #key:K;  #hash:string;constructor(key:K,requestFn:RequestFn<K,T>){this.#key=key;this.#requestFn=requestFn;this.#hash=stableHash(key);this.request();}mutate=(fn:(current:T|null)=>T|null)=>{this.#state.data=fn(this.#state.data);};request=():Promise<T|null>=>{this.#state={data:null,error:null,status:'loading'};returnthis.#requestFn(this.#key).then((r)=>{this.#state={data:r,error:null,status:'completed'};returnr;}).catch((e)=>{this.#state={data:null,error:e,status:'errored'};returnnull;});};getstate(){returnthis.#state;}gethash(){returnthis.#hash;}}

Components can access a cached request via:

constgetRequestCache=<KextendsStableKey,T>(key:K,requestFn:RequestFn<K,T>,):RequestCache<K,T>=>{consthash=stableHash(key);if(globalRequestCacheStore==null){thrownewError('globalRequestCacheStore not initialized');}constexisting=globalRequestCacheStore.get(hash);if(existing){returnexistingasRequestCache<K,T>;}constinstance=newRequestCache<K,T>(key,requestFn);globalRequestCacheStore.set(hash,instance);returninstance;};

Which you can wrap like:

exportconstgetNote=(token:string,id:number)=>{// getRequestCache(key, fetcher)returngetRequestCache({url:`http://api.com/note/${id}`, token},async({ url, token})=>{awaitsleep(2000);return{ url, token,note:'I am a note!'};});};

And then in a child component:

const{ id}=$props();constrequestInstance=getNote('my-token',id);// requestInstance.state.status === "loading"

⚠️ The Problem

Whenid changes (via props), thegetNote call is still referring to the cached instance for the oldid, because the component doesn't callgetNote again. You can wrap it with$derive because it creates an object and stores it ($derive must not include unsafe mutations or side effects)
My workaround for now is to force Svelte to recreate the child by wrapping it in a#key block:

{#keyid}  <Noteid={id} />{/key}

This works, but feels awkward — perhaps even an anti-pattern.

Describe the proposed solution

It would be nice the Svelte team provide an official, idiomatic recommendation for implementing aglobal request cache in Svelte, similar in spirit to howReact Query orSWR work in React.

This would make it easy to:
Easily share and reuse async request state (data,loading,error) across multiple components.
Mutate and revalidate cached data from anywhere in the app, enabling patterns like optimistic updates, rollbacks on error, manual refresh actions, or keeping related views (e.g., a list of notes) in sync when items are created, updated, or deleted.
Ensure cached data remains consistent and reactive throughout the app, reflecting the latest state without manual intervention.

A recommended pattern, utility, or built-in API to support this common use case would be very helpful.

Importance

would make my life easier

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp