Awesome-omni-skill solid-router-queries

Solid Router queries: query() for data fetching with caching/deduplication, createAsync() for reactive signals, createAsyncStore() for fine-grained reactivity, query keys for revalidation.

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/frontend/solid-router-queries" ~/.claude/skills/diegosouzapw-awesome-omni-skill-solid-router-queries && rm -rf "$T"
manifest: skills/frontend/solid-router-queries/SKILL.md
source content

Solid Router Queries

Defining Queries

Queries provide caching, deduplication, and revalidation:

import { query } from "@solidjs/router";

const getUserQuery = query(async (userId: string) => {
  const response = await fetch(`/api/users/${userId}`);
  if (!response.ok) {
    throw new Error("Failed to fetch user");
  }
  return response.json();
}, "user");

Query features:

  • Automatic request deduplication
  • Caching for preloading and navigation
  • Server-side deduplication in SSR
  • Automatic revalidation after actions
  • Browser history navigation reuse

Using Queries with createAsync

import { Show, Suspense, ErrorBoundary } from "solid-js";
import { createAsync, query } from "@solidjs/router";

const getUserQuery = query(async (id: string) => {
  // Fetch user
}, "user");

function UserProfile(props: { userId: string }) {
  const user = createAsync(() => getUserQuery(props.userId));
  
  return (
    <ErrorBoundary fallback={<div>Error loading user</div>}>
      <Suspense fallback={<div>Loading...</div>}>
        <Show when={user()}>
          <div>{user()!.name}</div>
        </Show>
      </Suspense>
    </ErrorBoundary>
  );
}

createAsync Options

const data = createAsync(() => getDataQuery(), {
  name: "myData",        // Debug name
  initialValue: [],      // Initial value before fetch
  deferStream: true      // Wait for data before streaming (SSR)
});

deferStream: Set to

true
when data is critical for SEO or initial render.

createAsyncStore

For large datasets that need fine-grained reactivity:

import { createAsyncStore } from "@solidjs/router";

const getNotificationsQuery = query(async (unreadOnly: boolean) => {
  // Fetch notifications
}, "notifications");

function Notifications() {
  const notifications = createAsyncStore(() =>
    getNotificationsQuery(false),
    { initialValue: [] }
  );
  
  // Access as store (direct property access)
  return (
    <For each={notifications()}>
      {(notification) => (
        <div>{notification.message}</div>
      )}
    </For>
  );
}

Use

createAsyncStore
when:

  • Working with large, complex data structures
  • Need fine-grained reactivity on nested properties
  • Want reconciliation when data updates

cache (Deprecated)

Note:

cache
is deprecated since v0.15.0. Use
query
instead.

// ❌ Deprecated
import { cache } from "@solidjs/router";
const getUser = cache(async (id) => fetchUser(id), "user");

// ✅ Use query instead
import { query } from "@solidjs/router";
const getUser = query(async (id) => fetchUser(id), "user");

Query Keys

Query keys are generated from name and arguments. Access for revalidation:

const getProductQuery = query(async (id: string) => {
  // ...
}, "product");

// Base key - revalidates all instances
getProductQuery.key

// Specific key - revalidates one instance
getProductQuery.keyFor("123")

Best Practices

  1. Wrap async data with
    <Suspense>
    and
    <ErrorBoundary>
  2. Use
    deferStream: true
    for SEO-critical data
  3. Use query names for debugging and devtools
  4. Use
    createAsyncStore
    for complex nested data
  5. Access query keys for manual revalidation when needed