Agent skill
solid-core-advanced-utilities
SolidJS advanced utilities: createRoot for manual disposal, createUniqueId for SSR-safe IDs, useTransition for batching async updates, observable for RxJS interop, modifyMutable for batch updates.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/solid-core-advanced-utilities
SKILL.md
Advanced Utilities
createRoot
Creates a new owned context requiring explicit disposal. Essential for manual memory management and testing.
import { createRoot } from "solid-js";
createRoot((dispose) => {
const [count, setCount] = createSignal(0);
createEffect(() => {
console.log(count());
});
// Explicitly dispose when done
dispose();
});
Use cases:
- Testing (ensures cleanup)
- Manual memory management
- Nested tracking scopes
- Top-level code wrapping
Example in tests:
test("counter works", () => {
createRoot((dispose) => {
const { count, increment } = createCounter();
expect(count()).toBe(0);
increment();
expect(count()).toBe(1);
dispose(); // Clean up
});
});
Returning values:
const counter = createRoot((dispose) => {
const [count, setCount] = createSignal(0);
return {
value: count,
increment: () => setCount(c => c + 1),
dispose
};
});
createUniqueId
Generates SSR-safe unique IDs. Stable across server and client renders.
import { createUniqueId } from "solid-js";
function Input(props: { id?: string }) {
const id = props.id ?? createUniqueId();
return (
<>
<label for={id}>Name</label>
<input id={id} />
</>
);
}
Requirements:
- Must be called same number of times on server and client
- Cannot use conditionally with
isServeror inside<NoHydration> - Not cryptographically secure
- Not suitable for distributed systems
Use cases:
- Form element IDs
- Accessibility (aria-labelledby, etc.)
- SSR-compatible unique identifiers
useTransition
Batches async updates, deferring commit until all async processes complete. Tied to Suspense.
import { useTransition } from "solid-js";
const [isPending, start] = useTransition();
// Check if transitioning
isPending();
// Wrap in transition
start(() => {
setSignal(newValue);
// transition is done
});
Features:
- Batches async updates in transaction
- Tracks resources read under Suspense boundaries
isPending()indicates transition state- Returns promise when transition completes
Use case: Smooth UI transitions with async data loading.
observable
Converts signals to Observables for RxJS integration.
import { observable } from "solid-js";
import { from } from "rxjs";
const [s, set] = createSignal(0);
const obsv$ = from(observable(s));
obsv$.subscribe((v) => console.log(v));
Use case: Integrating with RxJS or other Observable libraries.
modifyMutable
Batches multiple mutable store changes. Updates multiple fields in one render cycle.
import { modifyMutable, reconcile, produce } from "solid-js/store";
const state = createMutable({
user: {
firstName: "John",
lastName: "Smith",
},
});
// Multiple updates trigger multiple renders
state.user.firstName = "Jane";
state.user.lastName = "Doe";
// Batch updates with modifyMutable
modifyMutable(state.user, reconcile({
firstName: "Jane",
lastName: "Doe",
}));
// Or with produce
modifyMutable(state, produce((state) => {
state.user.firstName = "Jane";
state.user.lastName = "Doe";
}));
Benefits:
- Single render cycle for multiple changes
- Works with
reconcileandproduce - Better performance for complex updates
getOwner / runWithOwner
Advanced ownership patterns for nested contexts.
import { getOwner, runWithOwner } from "solid-js";
const owner = getOwner();
// Run code with specific owner
runWithOwner(owner, () => {
// Code runs in owner's context
});
Use case: Advanced scenarios requiring specific owner context (rare).
Best Practices
-
createRoot:
- Always use in tests for proper cleanup
- Use for manual memory management
- Return dispose function when creating reusable primitives
-
createUniqueId:
- Use for form elements and accessibility
- Call same number of times on server/client
- Don't use conditionally based on server/client
-
useTransition:
- Use with Suspense boundaries
- Check
isPending()for loading states - Batch related async updates
-
modifyMutable:
- Use for batch updates to mutable stores
- Combine with
reconcileorproduce - Prefer over multiple direct mutations
Didn't find tool you were looking for?