DEV Community

Alex Spinov
Alex Spinov

Posted on

SolidJS Has a Free API You Should Know About

SolidJS has one of the most elegant reactive APIs in the JavaScript ecosystem. Fine-grained reactivity without a virtual DOM — and SolidStart adds full-stack capabilities.

Reactive Primitives

Solid's core reactivity API:

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

// Signals — reactive state
const [count, setCount] = createSignal(0)
const [user, setUser] = createSignal({ name: "Alice", score: 0 })

// Derived values — only recompute when dependencies change
const doubled = createMemo(() => count() * 2)
const greeting = createMemo(() => `Hello, ${user().name}!`)

// Effects — run when dependencies change
createEffect(() => {
  console.log(`Count is now: ${count()}`)
  // Automatically tracks count() as dependency
})

// Batch updates
import { batch } from "solid-js"
batch(() => {
  setCount(10)
  setUser({ name: "Bob", score: 100 })
})
Enter fullscreen mode Exit fullscreen mode

Stores — Deep Reactive Objects

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

const [state, setState] = createStore({
  users: [
    { id: 1, name: "Alice", tasks: ["Code", "Review"] },
    { id: 2, name: "Bob", tasks: ["Design"] }
  ],
  filter: "all"
})

// Granular updates — only affected DOM nodes update
setState("users", 0, "name", "Alice Updated")
setState("filter", "active")

// Immer-like produce
setState(produce((s) => {
  s.users.push({ id: 3, name: "Charlie", tasks: [] })
  s.users[0].tasks.push("Deploy")
}))
Enter fullscreen mode Exit fullscreen mode

Resources — Async Data Fetching

import { createResource, Suspense } from "solid-js"

const [userId, setUserId] = createSignal("1")

const [user, { refetch, mutate }] = createResource(
  userId, // Source signal
  async (id) => {
    const res = await fetch(`/api/users/${id}`)
    return res.json()
  }
)

// In JSX
function UserProfile() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Show when={user()} fallback={<p>No user</p>}>
        <h1>{user().name}</h1>
        <p>{user().email}</p>
      </Show>
    </Suspense>
  )
}

// Optimistic update
mutate(prev => ({ ...prev, name: "Updated" }))
refetch()
Enter fullscreen mode Exit fullscreen mode

SolidStart — Full-Stack API

Server functions and API routes:

// src/routes/api/posts.js
import { json } from "@solidjs/router"

export async function GET() {
  const posts = await db.post.findMany()
  return json(posts)
}

export async function POST({ request }) {
  const body = await request.json()
  const post = await db.post.create({ data: body })
  return json(post, { status: 201 })
}
Enter fullscreen mode Exit fullscreen mode

Server Functions (RPC)

"use server"

import { db } from "~/lib/db"

export async function getUser(id) {
  return db.user.findUnique({ where: { id } })
}

export async function createPost(title, content) {
  return db.post.create({ data: { title, content } })
}
Enter fullscreen mode Exit fullscreen mode
import { getUser, createPost } from "~/server/actions"

function Dashboard() {
  const [user] = createResource(() => getUser("123"))

  const handleCreate = async () => {
    await createPost("New Post", "Content here")
  }

  return <button onClick={handleCreate}>Create Post</button>
}
Enter fullscreen mode Exit fullscreen mode

Context API

import { createContext, useContext } from "solid-js"

const ThemeContext = createContext("light")

function ThemeProvider(props) {
  const [theme, setTheme] = createSignal("light")
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {props.children}
    </ThemeContext.Provider>
  )
}

function ThemedButton() {
  const { theme, setTheme } = useContext(ThemeContext)
  return (
    <button
      class={theme() === "dark" ? "btn-dark" : "btn-light"}
      onClick={() => setTheme(t => t === "dark" ? "light" : "dark")}
    >
      Toggle Theme
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Signals for fine-grained reactive state
  • Stores for deep reactive objects with granular updates
  • Resources for async data with Suspense
  • createMemo/createEffect for derived values and side effects
  • SolidStart for full-stack with server functions
  • No virtual DOM — direct DOM updates for peak performance

Explore Solid docs for the complete API.


Building web scrapers or data pipelines? Check out my Apify actors for ready-made solutions, or email spinov001@gmail.com for custom development.

Top comments (0)