SolidJS Cheat Sheet
Quick reference for SolidJS — signals, effects, stores, control flow, context, and component patterns. Build fast reactive UIs with fine-grained reactivity.
Getting Started
Signals (Reactive State)
Effects & Memos
Control Flow Components
Stores (Deep Reactivity)
Context & Props
SolidStart (Meta-Framework)
Getting Started
| npx degit solidjs/templates/ts my-app | Create TypeScript project |
| npx degit solidjs/templates/js my-app | Create JavaScript project |
| npm create solid@latest | Create with SolidStart (meta-framework) |
| npm run dev | Start dev server (Vite) |
| npm run build | Build for production |
| import { render } from "solid-js/web" | Import render function |
| render(() => |
Mount app to DOM |
Signals (Reactive State)
| const [count, setCount] = createSignal(0) | Create a signal (getter + setter) |
| count() | Read signal value (call as function!) |
| setCount(5) | Set signal to value |
| setCount(prev => prev + 1) | Update based on previous value |
| const doubled = () => count() * 2 | Derived value (just a function) |
| const [user, setUser] = createSignal({ name: "Alice" }) | Signal with object |
| setUser({ ...user(), name: "Bob" }) | Update object signal (replace) |
Effects & Memos
| createEffect(() => { console.log(count()) }) | Run side effect when dependencies change |
| createEffect(on(count, (v) => { ... })) | Explicit dependency tracking |
| createEffect(on(count, (v) => { ... }, { defer: true })) | Skip initial run |
| const value = createMemo(() => expensiveCalc(count())) | Cached derived value |
| onMount(() => { ... }) | Run once after component mounts |
| onCleanup(() => { ... }) | Cleanup on component unmount |
| const [data] = createResource(fetchUser) | Async data fetching |
| const [data] = createResource(userId, fetchUser) | Resource with source signal |
Control Flow Components
| Conditional rendering | |
| List rendering (keyed by reference) | |
| List rendering (keyed by index) | |
| Switch/match rendering | |
| Dynamic component selection | |
| Render outside component tree | |
{err.message} }>... |
Error boundary |
| Suspense for async resources |
Stores (Deep Reactivity)
| const [store, setStore] = createStore({ todos: [], filter: "all" }) | Create store (deep reactive) |
| store.todos[0].text | Read nested store property |
| setStore("filter", "active") | Set top-level property |
| setStore("todos", todo => [...todo, newTodo]) | Update array in store |
| setStore("todos", 0, "completed", true) | Update nested property by path |
| setStore("todos", t => t.id === id, "completed", c => !c) | Update by predicate |
| const [state, setState] = createStore({}, { name: "debug" }) | Named store (DevTools) |
| import { produce } from "solid-js/store" | Immer-like mutations |
| setStore(produce(s => { s.todos.push(newTodo) })) | Mutate store with produce |
Context & Props
| const ThemeCtx = createContext("light") | Create context with default |
| Provide context value | |
| const theme = useContext(ThemeCtx) | Consume context |
| const [local, others] = splitProps(props, ["class", "children"]) | Split props (avoid destructuring!) |
| const merged = mergeProps({ size: "md" }, props) | Merge props with defaults |
| props.children | Access children (do NOT destructure props) |
| Polymorphic component pattern |
SolidStart (Meta-Framework)
| src/routes/index.tsx | → / (file-based routing) |
| src/routes/blog/[slug].tsx | → /blog/:slug (dynamic route) |
| export default function Page() { ... } | Page component |
| "use server" | Mark function as server-only |
| const data = createAsync(() => getUser()) | Server function + async data |
| const submit = useAction(createTodo) | Use server action for mutations |
| About | Client-side navigation link |
| export const route = { preload: () => getUser() } | Preload data for route |
Try It Live
Test these patterns with our free JSON Formatter. No signup needed.
Open JSON Formatter →
Step-by-Step Guide
Read Guide →