| name | solid-agents-review |
| description | Use when reviewing generated SolidJS code, validating a SolidJS project, or checking for React pattern contamination. Prevents silent reactivity breaks from incorrect signal access, destructured props, wrong control flow, and store mutation errors. Covers signal access patterns, control flow components, props handling, store mutations, event handling, and context usage. Keywords: SolidJS review, code validation, React contamination, signal access, createSignal, Show, For, props, stores.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires SolidJS 1.x/2.x. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
solid-agents-review
Quick Reference
Run this checklist on EVERY generated SolidJS code block. Each item has a severity level:
- CRITICAL -- Breaks reactivity silently. Code appears to work but updates fail.
- WARNING -- Suboptimal pattern. Works but causes performance issues or maintenance problems.
- INFO -- Style issue. Does not break functionality but violates SolidJS idioms.
1. Signal Access Checks
CRITICAL: Signals MUST be called as functions in JSX and reactive scopes
const [count, setCount] = createSignal(0);
return <div>{count}</div>;
return <div>{count()}</div>;
CRITICAL: NEVER store signal results in variables outside reactive scopes
const value = count();
return <div>{value}</div>;
return <div>{count()}</div>;
CRITICAL: NEVER destructure signal getters from arrays or objects
const currentCount = count();
const doubled = createMemo(() => count() * 2);
WARNING: Use createMemo for derived values, NOT createEffect + setSignal
const [doubled, setDoubled] = createSignal(0);
createEffect(() => setDoubled(count() * 2));
const doubled = createMemo(() => count() * 2);
CRITICAL: NEVER access signals conditionally before other signals in effects
createEffect(() => {
if (loading()) return;
console.log(name());
});
createEffect(() => {
const isLoading = loading();
const currentName = name();
if (isLoading) return;
console.log(currentName);
});
2. Props Checks
CRITICAL: NEVER destructure props
function Greeting({ name }: { name: string }) {
return <h1>{name}</h1>;
}
function Greeting(props: { name: string }) {
const { name } = props;
return <h1>{name}</h1>;
}
function Greeting(props: { name: string }) {
return <h1>{props.name}</h1>;
}
WARNING: Use splitProps to separate prop groups reactively
const [local, others] = splitProps(props, ["class", "onClick"]);
return <div class={local.class} {...others} />;
WARNING: Use mergeProps for default prop values
const merged = mergeProps({ variant: "primary" }, props);
return <button class={merged.variant}>{props.children}</button>;
WARNING: Use children() helper when manipulating props.children
const kids = props.children;
import { children } from "solid-js";
const resolved = children(() => props.children);
return <div>{resolved()}</div>;
3. Control Flow Checks
WARNING: Use <For> instead of Array.map for list rendering
{items().map((item) => <div key={item.id}>{item.name}</div>)}
<For each={items()}>
{(item) => <div>{item.name}</div>}
</For>
WARNING: Use <Show> instead of ternary for conditional rendering
{isLoggedIn() ? <Dashboard /> : <Login />}
<Show when={isLoggedIn()} fallback={<Login />}>
<Dashboard />
</Show>
WARNING: Use <Switch>/<Match> instead of switch statements or chained ternaries
<Switch fallback={<NotFound />}>
<Match when={route() === "home"}><Home /></Match>
<Match when={route() === "about"}><About /></Match>
</Switch>
INFO: NEVER use the key prop -- SolidJS <For> tracks by reference
<For each={items()}>
{(item) => <div key={item.id}>{item.name}</div>}
</For>
<For each={items()}>
{(item) => <div>{item.name}</div>}
</For>
INFO: Use <Index> for arrays of primitives, <For> for arrays of objects
4. Store Checks
CRITICAL: NEVER destructure store properties
const { username } = store.users[0];
<span>{store.users[0].username}</span>
CRITICAL: Use setStore path syntax for updates, NEVER spread-replace
setStore({ ...store, count: store.count + 1 });
setStore("count", (c) => c + 1);
setStore("users", 0, "loggedIn", true);
WARNING: Use produce for complex mutations
setStore(produce((state) => {
state.users.push(newUser);
state.count += 1;
}));
5. Component Checks
CRITICAL: NEVER use early returns for conditional rendering
function Profile(props: { user: User | null }) {
if (!props.user) return <p>Loading...</p>;
return <div>{props.user.name}</div>;
}
function Profile(props: { user: User | null }) {
return (
<Show when={props.user} fallback={<p>Loading...</p>}>
{(user) => <div>{user().name}</div>}
</Show>
);
}
WARNING: Use correct event binding patterns
<button onClick={handleClick()}>Click</button>
<button onClick={handleClick}>Click</button>
<button onClick={() => handleClick(id)}>Click</button>
<button onClick={[handleClick, id]}>Click</button>
INFO: Use let ref!: HTMLElement for refs, NOT useRef
let inputRef!: HTMLInputElement;
onMount(() => inputRef.focus());
return <input ref={inputRef} />;
INFO: Declare directives in module scope for TypeScript
declare module "solid-js" {
namespace JSX {
interface Directives {
clickOutside: () => void;
}
}
}
6. React Contamination Scan
CRITICAL: Scan for ALL React imports and hooks
NEVER allow these in SolidJS code:
| React Pattern | SolidJS Replacement |
|---|
useState | createSignal |
useEffect | createEffect |
useMemo | createMemo |
useRef | let ref!: T |
useCallback | Not needed (no re-renders) |
useContext | useContext (same name, different import) |
forwardRef | Pass ref as regular prop |
React.createElement | SolidJS JSX compiler |
React.memo | Not needed (no re-renders) |
useReducer | createStore |
CRITICAL: NEVER use dependency arrays
createEffect(() => {
console.log(count());
}, [count]);
createEffect(() => {
console.log(count());
});
CRITICAL: NEVER return cleanup from effects
createEffect(() => {
const id = setInterval(fn, 1000);
return () => clearInterval(id);
});
createEffect(() => {
const id = setInterval(fn, 1000);
onCleanup(() => clearInterval(id));
});
CRITICAL: NEVER use element={} on Route definitions
<Route path="/" element={<Home />} />
<Route path="/" component={Home} />
Review Procedure
Execute these checks in order on every generated SolidJS code block:
- Import scan -- Flag ANY import from
react, react-dom, react-router-dom
- Hook scan -- Flag
useState, useEffect, useMemo, useRef, useCallback, useReducer, forwardRef
- Signal access -- Verify ALL signals are called as functions
signal() in JSX
- Props handling -- Verify NO destructuring of props objects
- Control flow -- Verify
<For>, <Show>, <Switch> used instead of .map(), ternaries, switch statements
- Store access -- Verify NO destructuring of store properties
- Store updates -- Verify path syntax used, no spread-replace
- Early returns -- Verify NO early returns in component bodies for conditional rendering
- Cleanup -- Verify
onCleanup() used, NOT return from effects
- Dependency arrays -- Verify NO
[deps] passed to createEffect/createMemo
- key prop -- Flag any usage of
key={} in JSX
- Refs -- Verify
let ref!: T pattern, NOT useRef
Reference Links
Official Sources