Skip to content

Cached Models ​

Use a model cache when unmounting a component should not destroy its model.

This is useful for chats, editor tabs, media players, previews, and detail screens that should reopen with their previous state. A cache is also a lifetime decision: the model will stay in memory until you delete it or clear the cache.

Key The Model ​

Cached models are stored by key inside a scope. For a chat, the key can be chatId. For editor tabs, it can be a document id. The key should describe the thing the user expects to return to.

ts
import { component, createModelCache } from "@virentia/vue";

const chatCache = createModelCache<string, Props, ChatModel>();

export const ChatPanel = component({
  cache: chatCache,
  key: (props: Props) => props.chatId,
  model: createChatModel,
  view: ChatPanelView,
});

When ChatPanel unmounts, the cached model stays alive. When the same key appears again in the same scope, Vue gets the existing model instead of creating a fresh one.

You can also cache with useModel by passing { cache, key }:

ts
const model = useModel(createChatModel, () => props, {
  cache: chatCache,
  key: props.chatId,
});

Loading Logic In The Model ​

The model can use mounted to load data the first time it appears:

ts
import { effect, reaction, store } from "@virentia/core";
import type { ModelContext } from "@virentia/vue";

function createChatModel({ key, mounted }: ModelContext<Props, string>) {
  const messages = store({ items: [] as string[] });
  const loadFx = effect(async (chatId: string) => [`loaded:${chatId}`]);

  reaction({
    on: mounted,
    run() {
      void loadFx(key);
    },
  });

  return { loading: loadFx.pending, messages };
}

For cached models, think carefully about whether mounted should reload every time a view returns or only when the model is first created. If reloads are expensive, keep an additional store like loaded and guard the reaction.

Dispose Deliberately ​

Caching trades memory for continuity. Delete a model when the user closes the chat, tab, player, or preview for good.

ts
chatCache.delete("support", appScope);
chatCache.clear(appScope);

Deleting a cached model disposes its owner, so reactions and cleanup registered inside the model are detached as well.