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
// WRONG -- signal value read once, never updates
const [count, setCount] = createSignal(0);
return <div>{count}</div>;
// CORRECT -- signal called as function, tracked reactively
return <div>{count()}</div>;
CRITICAL: NEVER store signal results in variables outside reactive scopes
// WRONG -- snapshot, never updates
const value = count();
return <div>{value}</div>;
// CORRECT -- call getter where the value is needed
return <div>{count()}</div>;
CRITICAL: NEVER destructure signal getters from arrays or objects
// WRONG -- extracted once, loses tracking
const currentCount = count();
// CORRECT -- use createMemo for derived state
const doubled = createMemo(() => count() * 2);
WARNING: Use createMemo for derived values, NOT createEffect + setSignal
// WRONG -- unnecessary effect/signal pair
const [doubled, setDoubled] = createSignal(0);
createEffect(() => setDoubled(count() * 2));
// CORRECT -- createMemo caches derived state
const doubled = createMemo(() => count() * 2);
CRITICAL: NEVER access signals conditionally before other signals in effects
// WRONG -- name() not tracked when loading() is true
createEffect(() => {
if (loading()) return;
console.log(name());
});
// CORRECT -- access all signals first, then use conditionally
createEffect(() => {
const isLoading = loading();
const currentName = name();
if (isLoading) return;
console.log(currentName);
});
2. Props Checks
CRITICAL: NEVER destructure props
// WRONG -- kills reactivity
function Greeting({ name }: { name: string }) {
return <h1>{name}</h1>;
}
// WRONG -- also kills reactivity
function Greeting(props: { name: string }) {
const { name } = props;
return <h1>{name}</h1>;
}
// CORRECT -- access props directly
function Greeting(props: { name: string }) {
return <h1>{props.name}</h1>;
}
WARNING: Use splitProps to separate prop groups reactively
// CORRECT -- preserves reactivity while splitting
const [local, others] = splitProps(props, ["class", "onClick"]);
return <div class={local.class} {...others} />;
WARNING: Use mergeProps for default prop values
// CORRECT -- reactive defaults
const merged = mergeProps({ variant: "primary" }, props);
return <button class={merged.variant}>{props.children}</button>;
WARNING: Use children() helper when manipulating props.children
// WRONG -- may re-create children on each access
const kids = props.children;
// CORRECT -- resolve and cache 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
// WRONG -- re-creates all DOM nodes on change
{items().map((item) => <div key={item.id}>{item.name}</div>)}
// CORRECT -- fine-grained updates per item
<For each={items()}>
{(item) => <div>{item.name}</div>}
</For>
WARNING: Use <Show> instead of ternary for conditional rendering
// WRONG -- can cause unnecessary DOM recreation
{isLoggedIn() ? <Dashboard /> : <Login />}
// CORRECT -- reactive conditional rendering
<Show when={isLoggedIn()} fallback={<Login />}>
<Dashboard />
</Show>
WARNING: Use <Switch>/<Match> instead of switch statements or chained ternaries
// CORRECT
<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
// WRONG -- key prop is ignored in SolidJS
<For each={items()}>
{(item) => <div key={item.id}>{item.name}</div>}
</For>
// CORRECT -- no key needed
<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
// WRONG -- snapshot, loses reactivity
const { username } = store.users[0];
// CORRECT -- access in tracking scope
<span>{store.users[0].username}</span>
CRITICAL: Use setStore path syntax for updates, NEVER spread-replace
// WRONG -- replaces entire state, breaks fine-grained tracking
setStore({ ...store, count: store.count + 1 });
// CORRECT -- surgical path update
setStore("count", (c) => c + 1);
setStore("users", 0, "loggedIn", true);
WARNING: Use produce for complex mutations
// CORRECT -- Immer-style mutations applied immutably
setStore(produce((state) => {
state.users.push(newUser);
state.count += 1;
}));
5. Component Checks
CRITICAL: NEVER use early returns for conditional rendering
// WRONG -- component body runs once, early return is permanent
function Profile(props: { user: User | null }) {
if (!props.user) return <p>Loading...</p>;
return <div>{props.user.name}</div>;
}
// CORRECT -- use Show for reactive conditional
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
// WRONG -- calls handler immediately, assigns return value
<button
// CORRECT -- passes handler reference
<button
// CORRECT -- arrow function for arguments
<button => handleClick(id)}>Click</button>
// CORRECT -- array syntax avoids closure creation
<button id]}>Click</button>
INFO: Use let ref!: HTMLElement for refs, NOT useRef
// CORRECT
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
// WRONG -- dependency arrays are a React concept
createEffect(() => {
console.log(count());
}, [count]);
// CORRECT -- automatic tracking, no deps
createEffect(() => {
console.log(count());
});
CRITICAL: NEVER return cleanup from effects
// WRONG -- React cleanup pattern
createEffect(() => {
const id = setInterval(fn, 1000);
return () => clearInterval(id);
});
// CORRECT -- use onCleanup
createEffect(() => {
const id = setInterval(fn, 1000);
onCleanup(() => clearInterval(id));
});
CRITICAL: NEVER use element={} on Route definitions
// WRONG -- React Router pattern
<Route path="/" element={<Home />} />
// CORRECT -- Solid Router pattern
<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!: Tpattern, NOTuseRef
Reference Links
- references/methods.md -- Complete validation checklist organized by area
- references/examples.md -- Review scenarios with good code, bad code, and fixes
- references/anti-patterns.md -- All React contamination patterns consolidated for scanning
Official Sources
- https://docs.solidjs.com/concepts/intro-to-reactivity
- https://docs.solidjs.com/concepts/components/props
- https://docs.solidjs.com/reference/basic-reactivity/create-signal
- https://docs.solidjs.com/reference/basic-reactivity/create-effect
- https://docs.solidjs.com/reference/basic-reactivity/create-memo
- https://docs.solidjs.com/reference/store-utilities/create-store
- https://docs.solidjs.com/reference/components/for
- https://docs.solidjs.com/reference/components/show