AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Solid Impl State Patterns

skill-impertio-studio-solidjs-claude-skill-package-solid-impl-state-patterns · by Impertio-Studio

>

No reviews yet
0 installs
27 views
0.0% view→install

Install

$ agentstack add skill-impertio-studio-solidjs-claude-skill-package-solid-impl-state-patterns

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-impertio-studio-solidjs-claude-skill-package-solid-impl-state-patterns)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Solid Impl State Patterns? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

solid-impl-state-patterns

Quick Reference

State Primitives Overview

| Primitive | Import | Use Case | Access Syntax | |-----------|--------|----------|---------------| | createSignal | solid-js | Single values, primitives, toggles | signal() (getter function) | | createStore | solid-js/store | Nested objects, arrays, complex state | store.prop (direct access) | | createContext | solid-js | Shared state across component tree | Provider + useContext | | createMemo | solid-js | Derived/computed values | memo() (getter function) | | createMutable | solid-js/store | MobX/Vue migration only | state.prop (direct mutation) |

Critical Warnings

NEVER use createEffect to synchronize derived state — ALWAYS use createMemo instead. Effects are for side effects (DOM, network, logging), not for computing values from other signals.

NEVER store signal values in variables outside tracking scopes — the variable captures a snapshot, not a reactive binding. ALWAYS call the getter function where you need the current value.

NEVER destructure props or stores — destructuring reads values once and breaks reactive tracking. ALWAYS access properties through the proxy object.

NEVER use Redux, useReducer, or Zustand patterns — SolidJS has built-in primitives (signals, stores, context) that are more efficient and idiomatic.

NEVER use global mutable variables for shared state — ALWAYS use createContext + createStore for type-safe, reactive, scoped state sharing.


State Selection Decision Tree

Need state? → What kind of data?
│
├─ Single primitive value (string, number, boolean)
│  → createSignal
│
├─ Object with nested properties / array of items
│  → createStore
│
├─ Derived from other state (computed value)
│  → createMemo (NEVER createEffect + createSignal)
│
├─ Shared across multiple components
│  │
│  ├─ Parent → children (1-2 levels deep)
│  │  → Pass as props (direct)
│  │
│  └─ Across distant components / app-wide
│     → createContext + createStore + Provider
│
├─ Async data from server/API
│  → createResource (SolidJS 1.x) or createAsync (with @solidjs/router)
│
└─ External reactive source (RxJS, custom)
   → from() utility

When to Use Signals vs Stores

| Scenario | Use Signal | Use Store | |----------|-----------|-----------| | Counter, toggle, input value | YES | No | | User profile object | No | YES | | List of items (todos, products) | No | YES | | Theme (single string) | YES | No | | Form with multiple fields | No | YES | | Nested config object | No | YES | | Loading/error boolean | YES | No |


Global State Pattern: Context + Store

The canonical SolidJS pattern for shared state combines createContext, createStore, and a Provider component with a custom hook.

import { createContext, useContext, ParentProps } from "solid-js";
import { createStore, SetStoreFunction } from "solid-js/store";

// 1. Define state shape
interface AppState {
  user: { name: string; email: string } | null;
  theme: "light" | "dark";
  notifications: { id: string; message: string }[];
}

// 2. Define context type (state + actions)
type AppContextValue = [
  state: AppState,
  actions: {
    setUser: (user: AppState["user"]) => void;
    toggleTheme: () => void;
    addNotification: (message: string) => void;
    removeNotification: (id: string) => void;
  }
];

// 3. Create context (no default value — enforce Provider usage)
const AppContext = createContext();

// 4. Provider component with store + actions
export function AppProvider(props: ParentProps) {
  const [state, setState] = createStore({
    user: null,
    theme: "light",
    notifications: [],
  });

  const actions = {
    setUser: (user: AppState["user"]) => setState("user", user),
    toggleTheme: () =>
      setState("theme", (prev) => (prev === "light" ? "dark" : "light")),
    addNotification: (message: string) =>
      setState("notifications", (prev) => [
        ...prev,
        { id: crypto.randomUUID(), message },
      ]),
    removeNotification: (id: string) =>
      setState("notifications", (prev) => prev.filter((n) => n.id !== id)),
  };

  return (
    
      {props.children}
    
  );
}

// 5. Custom hook with safety check
export function useApp() {
  const context = useContext(AppContext);
  if (!context) throw new Error("useApp must be used within AppProvider");
  return context;
}

Usage in components:

function Header() {
  const [state, { toggleTheme }] = useApp();
  return (
    
      {state.user?.name ?? "Guest"}
      Theme: {state.theme}
    
  );
}

Derived State with createMemo

ALWAYS use createMemo for values computed from other reactive state. Memos cache results and only recompute when dependencies change.

import { createSignal, createMemo } from "solid-js";

const [items, setItems] = createSignal([]);
const [taxRate, setTaxRate] = createSignal(0.21);

// CORRECT: Derived values via createMemo
const subtotal = createMemo(() =>
  items().reduce((sum, item) => sum + item.price * item.qty, 0)
);
const tax = createMemo(() => subtotal() * taxRate());
const total = createMemo(() => subtotal() + tax());

// Memos chain: items/taxRate → subtotal → tax → total
// Changing taxRate recalculates tax and total, but NOT subtotal

Derived State Anti-Pattern

// WRONG: Using createEffect to sync derived state
const [count, setCount] = createSignal(0);
const [double, setDouble] = createSignal(0);

createEffect(() => {
  setDouble(count() * 2); // Unnecessary signal + effect cycle
});

// CORRECT: createMemo — no extra signal, no effect
const double = createMemo(() => count() * 2);

Form State Pattern

Store-Based Form (Recommended for Multi-Field Forms)

import { createStore } from "solid-js/store";
import { createSignal, Show } from "solid-js";

interface FormData {
  name: string;
  email: string;
  role: "admin" | "user" | "viewer";
}

interface FormErrors {
  name?: string;
  email?: string;
}

function UserForm() {
  const [form, setForm] = createStore({
    name: "",
    email: "",
    role: "user",
  });
  const [errors, setErrors] = createStore({});
  const [submitting, setSubmitting] = createSignal(false);

  const validate = (): boolean => {
    const newErrors: FormErrors = {};
    if (!form.name.trim()) newErrors.name = "Name is required";
    if (!form.email.includes("@")) newErrors.email = "Invalid email";
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = async (e: SubmitEvent) => {
    e.preventDefault();
    if (!validate()) return;
    setSubmitting(true);
    try {
      await saveUser(form);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    
       setForm("name", e.currentTarget.value)}
      />
      {errors.name}

       setForm("email", e.currentTarget.value)}
      />
      {errors.email}

       setForm("role", e.currentTarget.value as FormData["role"])}
      >
        Admin
        User
        Viewer
      

      
        {submitting() ? "Saving..." : "Save"}
      
    
  );
}

State Composition Strategies

splitProps for Prop Separation

import { splitProps } from "solid-js";

function Button(props: {
  variant: "primary" | "secondary";
  size: "sm" | "md" | "lg";
  onClick: () => void;
  children: any;
  class?: string;
  disabled?: boolean;
}) {
  const [local, others] = splitProps(props, ["variant", "size", "children"]);
  return (
    
      {local.children}
    
  );
}

Multiple Contexts (Feature Slicing)

ALWAYS create separate contexts for unrelated state domains. This prevents unnecessary re-computations.

// auth-context.tsx
export function AuthProvider(props: ParentProps) { /* ... */ }
export function useAuth() { /* ... */ }

// theme-context.tsx
export function ThemeProvider(props: ParentProps) { /* ... */ }
export function useTheme() { /* ... */ }

// Compose at app root
function App() {
  return (
    
      
        
      
    
  );
}

External State Integration with from()

import { from } from "solid-js";

// Bridge RxJS observable into SolidJS signal
const currentUser = from(userService.currentUser$);

// Bridge custom subscription
const windowWidth = from((set) => {
  const handler = () => set(window.innerWidth);
  window.addEventListener("resize", handler);
  handler(); // Set initial value
  return () => window.removeEventListener("resize", handler);
});

reconcile() for External Data Sync

import { createStore, reconcile } from "solid-js/store";

const [state, setState] = createStore({ todos: [] as Todo[] });

// Sync external data — only changed properties trigger updates
websocket.on("todos-updated", (newTodos: Todo[]) => {
  setState("todos", reconcile(newTodos));
});

Reference Links

  • [references/methods.md](references/methods.md) -- Pattern signatures for context+store, derived state, form state patterns
  • [references/examples.md](references/examples.md) -- Working code examples: global state, derived state, form management, counter/theme providers
  • [references/anti-patterns.md](references/anti-patterns.md) -- Redux patterns, prop drilling, global mutable variables, unnecessary state

Official Sources

  • https://docs.solidjs.com/concepts/signals
  • https://docs.solidjs.com/concepts/stores
  • https://docs.solidjs.com/concepts/context
  • https://docs.solidjs.com/reference/basic-reactivity/create-signal
  • https://docs.solidjs.com/reference/basic-reactivity/create-memo
  • https://docs.solidjs.com/reference/store-utilities/create-store
  • https://docs.solidjs.com/reference/reactive-utilities/from
  • https://docs.solidjs.com/reference/store-utilities/reconcile

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.