Getting Started with SolidJS
Getting Started with SolidJS
Section titled “Getting Started with SolidJS”This guide will help you get started with Effectify in your SolidJS application. We’ll walk through setting up the basic dependencies and creating your first Effect-powered SolidJS component.
Prerequisites
Section titled “Prerequisites”Before you begin, make sure you have:
- Node.js 18 or later
- A SolidJS application (Vite template, SolidStart, etc.)
- Basic knowledge of SolidJS and TypeScript
Installation
Section titled “Installation”Choose the packages you need for your project:
Core Query Package
Section titled “Core Query Package”For data fetching with TanStack Query and Effect:
npm install @effectify/solid-query @tanstack/solid-query effect solid-jsUI Components
Section titled “UI Components”For pre-built UI components:
npm install @effectify/solid-uiChat Components
Section titled “Chat Components”For real-time chat functionality:
npm install @effectify/chat-solidBasic Setup
Section titled “Basic Setup”1. Configure TanStack Query
Section titled “1. Configure TanStack Query”First, set up TanStack Query in your app root:
// src/App.tsx
import { QueryClient, QueryClientProvider } from "@tanstack/solid-query"
import { SolidQueryDevtools } from "@tanstack/solid-query-devtools"
const queryClient = new QueryClient()
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourAppComponents />
<SolidQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
export default App2. Create Your First Effect
Section titled “2. Create Your First Effect”Create a simple Effect that fetches data:
// src/effects/user.ts
import { Effect } from "effect"
export interface User {
id: number
name: string
email: string
}
export const fetchUser = (id: number) =>
Effect.tryPromise({
try: () => fetch(`/api/users/${id}`).then((res) => res.json()),
catch: (error) => new Error(`Failed to fetch user: ${error}`),
})3. Use Effect with SolidJS Resources
Section titled “3. Use Effect with SolidJS Resources”SolidJS provides createResource for async data fetching:
// src/components/UserProfile.tsx
import { createResource, Show } from "solid-js"
import { Effect } from "effect"
import { fetchUser } from "../effects/user"
interface UserProfileProps {
userId: number
}
export function UserProfile(props: UserProfileProps) {
const [user] = createResource(
() => props.userId,
(id) => Effect.runPromise(fetchUser(id)),
)
return (
<Show when={user()} fallback={<div>Loading...</div>}>
{(userData) => (
<div>
<h1>{userData().name}</h1>
<p>{userData().email}</p>
</div>
)}
</Show>
)
}4. Use Effect with TanStack Query
Section titled “4. Use Effect with TanStack Query”For more advanced caching and synchronization:
// src/components/UserProfileQuery.tsx
import { createQuery } from "@tanstack/solid-query"
import { Show } from "solid-js"
import { Effect } from "effect"
import { fetchUser } from "../effects/user"
interface UserProfileProps {
userId: number
}
export function UserProfileQuery(props: UserProfileProps) {
const userQuery = createQuery(() => ({
queryKey: ["user", props.userId],
queryFn: () => Effect.runPromise(fetchUser(props.userId)),
}))
return (
<Show when={userQuery.data} fallback={<div>Loading...</div>}>
{(user) => (
<div>
<h1>{user().name}</h1>
<p>{user().email}</p>
<Show when={userQuery.isError}>
<p class="error">Error: {userQuery.error?.message}</p>
</Show>
</div>
)}
</Show>
)
}Advanced Patterns
Section titled “Advanced Patterns”Reactive Effects with Signals
Section titled “Reactive Effects with Signals”Combine SolidJS signals with Effects:
import { createEffect, createSignal } from "solid-js"
import { Effect } from "effect"
function UserSearch() {
const [query, setQuery] = createSignal("")
const [results, setResults] = createSignal([])
const [loading, setLoading] = createSignal(false)
const searchUsers = (searchQuery: string) =>
Effect.tryPromise({
try: () =>
fetch(`/api/users/search?q=${searchQuery}`)
.then((res) => res.json()),
catch: (error) => new Error(`Search failed: ${error}`),
})
createEffect(() => {
const currentQuery = query()
if (currentQuery.length > 2) {
setLoading(true)
Effect.runPromise(
searchUsers(currentQuery).pipe(
Effect.tap((results) => Effect.sync(() => setResults(results))),
Effect.catchAll((error) => Effect.sync(() => console.error(error))),
Effect.finalize(() => Effect.sync(() => setLoading(false))),
),
)
}
})
return (
<div>
<input
type="text"
value={query()}
onInput={(e) => setQuery(e.currentTarget.value)}
placeholder="Search users..."
/>
<Show when={loading()}>
<div>Searching...</div>
</Show>
<ul>
<For each={results()}>
{(user) => <li>{user.name}</li>}
</For>
</ul>
</div>
)
}Error Handling with Effect
Section titled “Error Handling with Effect”Effect provides excellent error handling capabilities:
const fetchUserWithRetry = (id: number) =>
fetchUser(id).pipe(
Effect.retry({ times: 3, delay: "1 second" }),
Effect.catchAll((error) =>
Effect.succeed({
id,
name: "Unknown User",
email: "unknown@example.com",
})
),
)
function UserProfile(props: { userId: number }) {
const [user] = createResource(
() => props.userId,
(id) => Effect.runPromise(fetchUserWithRetry(id)),
)
return (
<Show when={user()} fallback={<div>Loading...</div>}>
{(userData) => (
<div>
<h1>{userData().name}</h1>
<p>{userData().email}</p>
</div>
)}
</Show>
)
}Combining Multiple Effects
Section titled “Combining Multiple Effects”You can compose multiple Effects together:
const fetchUserWithPosts = (id: number) =>
Effect.all([
fetchUser(id),
fetchUserPosts(id),
]).pipe(
Effect.map(([user, posts]) => ({ user, posts })),
)
function UserDashboard(props: { userId: number }) {
const [data] = createResource(
() => props.userId,
(id) => Effect.runPromise(fetchUserWithPosts(id)),
)
return (
<Show when={data()} fallback={<div>Loading dashboard...</div>}>
{(dashboardData) => (
<div>
<h1>{dashboardData().user.name}</h1>
<div>Posts: {dashboardData().posts.length}</div>
</div>
)}
</Show>
)
}Next Steps
Section titled “Next Steps”Now that you have the basics set up, explore the specific packages:
- Solid Query Integration - Learn advanced patterns for data fetching
- UI Components - Explore the component library
- Chat Components - Add real-time features
Common Patterns
Section titled “Common Patterns”Form Handling
Section titled “Form Handling”import { createSignal } from "solid-js"
import { Effect } from "effect"
const submitForm = (data: FormData) =>
Effect.tryPromise({
try: () =>
fetch("/api/submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
}).then((res) => res.json()),
catch: (error) => new Error(`Form submission failed: ${error}`),
})
function ContactForm() {
const [formData, setFormData] = createSignal({ name: "", email: "" })
const [submitting, setSubmitting] = createSignal(false)
const handleSubmit = (e: Event) => {
e.preventDefault()
setSubmitting(true)
Effect.runPromise(
submitForm(formData()).pipe(
Effect.tap(() => Effect.sync(() => console.log("Form submitted!"))),
Effect.catchAll((error) => Effect.sync(() => console.error(error))),
Effect.finalize(() => Effect.sync(() => setSubmitting(false))),
),
)
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={formData().name}
onInput={(e) =>
setFormData((prev) => ({
...prev,
name: e.currentTarget.value,
}))}
placeholder="Name"
/>
<input
type="email"
value={formData().email}
onInput={(e) =>
setFormData((prev) => ({
...prev,
email: e.currentTarget.value,
}))}
placeholder="Email"
/>
<button type="submit" disabled={submitting()}>
{submitting() ? "Submitting..." : "Submit"}
</button>
</form>
)
}Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”- Effect not running: Make sure to call
Effect.runPromise()in your resource function - Reactivity not working: Ensure you’re using SolidJS primitives correctly with Effects
- Type errors: Ensure you have the latest versions of Effect, SolidJS, and TypeScript
- Build errors: Check that all peer dependencies are installed
Getting Help
Section titled “Getting Help”If you run into issues:
- Check the GitHub Issues
- Join the Discussions
- Review the package-specific documentation
- Ask in the SolidJS Discord