Discover how to build lightning-fast web applications using Solid.js, a modern JavaScript framework that combines reactive programming with efficient DOM updates. 🚀
Why Solid.js? 🤔
Solid.js offers exceptional performance by updating only what needs to change, without using a virtual DOM. It provides a familiar React-like syntax while delivering superior runtime performance.
Project Setup
# Create new project
npm create vite@latest my-solid-app -- --template solid
cd my-solid-app
npm install
Basic Component Structure
// src/components/Counter.jsx
import { createSignal } from 'solid-js';
function Counter() {
const [count, setCount] = createSignal(0);
return (
<button onClick={() => setCount(count() + 1)}>
Clicks: {count()}
</button>
);
}
export default Counter;
Reactive Primitives 🔄
import { createSignal, createEffect, createMemo } from 'solid-js';
function Calculator() {
const [count, setCount] = createSignal(0);
const doubled = createMemo(() => count() * 2);
createEffect(() => {
console.log('Count changed:', count());
});
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
<p>Count: {count()}</p>
<p>Doubled: {doubled()}</p>
</div>
);
}
Props and Children
// Button.jsx
function Button(props) {
return (
<button
class={props.variant || 'primary'}
onClick={props.onClick}
>
{props.children}
</button>
);
}
// App.jsx
function App() {
return (
<Button
variant="secondary"
onClick={() => alert('Clicked!')}
>
Click Me
</Button>
);
}
State Management 📦
import { createStore } from 'solid-js/store';
function TodoList() {
const [todos, setTodos] = createStore([]);
const addTodo = (text) => {
setTodos([...todos, {
id: Date.now(),
text,
completed: false
}]);
};
const toggleTodo = (id) => {
setTodos(
todo => todo.id === id,
'completed',
completed => !completed
);
};
return (
<div>
<input
type="text"
onKeyPress={e => {
if (e.key === 'Enter') {
addTodo(e.target.value);
e.target.value = '';
}
}}
/>
<For each={todos}>
{(todo) => (
<div class="todo-item">
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span
style={{
'text-decoration': todo.completed ?
'line-through' : 'none'
}}
>
{todo.text}
</span>
</div>
)}
</For>
</div>
);
}
Control Flow 🔀
import { Show, For, Switch, Match } from 'solid-js';
function UserDashboard(props) {
return (
<div>
<Show
when={props.user}
fallback={<div>Loading...</div>}
>
<h1>Welcome, {props.user.name}!</h1>
</Show>
<Switch>
<Match when={props.view === 'profile'}>
<ProfileView user={props.user} />
</Match>
<Match when={props.view === 'settings'}>
<SettingsView user={props.user} />
</Match>
</Switch>
<For each={props.notifications}>
{(notification) => (
<div class="notification">
{notification.message}
</div>
)}
</For>
</div>
);
}
Resource Management 🌐
import { createResource } from 'solid-js';
function UserProfile(props) {
const [user] = createResource(() =>
fetch(`/api/users/${props.id}`)
.then(res => res.json())
);
return (
<Show
when={user()}
fallback={<div>Loading...</div>}
>
<div class="profile">
<h2>{user().name}</h2>
<p>{user().email}</p>
</div>
</Show>
);
}
Form Handling 📝
import { createStore } from 'solid-js/store';
function ContactForm() {
const [form, setForm] = createStore({
name: '',
email: '',
message: ''
});
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form data:', form);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input
value={form.name}
onInput={e => setForm('name', e.target.value)}
/>
</div>
<div>
<label>Email:</label>
<input
type="email"
value={form.email}
onInput={e => setForm('email', e.target.value)}
/>
</div>
<div>
<label>Message:</label>
<textarea
value={form.message}
onInput={e => setForm('message', e.target.value)}
/>
</div>
<button type="submit">Send</button>
</form>
);
}
Performance Optimization 🚀
Lazy Loading
import { lazy } from 'solid-js';
const HeavyComponent = lazy(() =>
import('./components/HeavyComponent')
);
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
Memo for Expensive Computations
import { createMemo } from 'solid-js';
function ExpensiveCalculation(props) {
const result = createMemo(() => {
// Expensive computation
return props.data.reduce((acc, val) => acc + val, 0);
});
return <div>Result: {result()}</div>;
}
Custom Hooks 🎣
import { createSignal, createEffect } from 'solid-js';
function useLocalStorage(key, initialValue) {
const storedValue = localStorage.getItem(key);
const [value, setValue] = createSignal(
storedValue ? JSON.parse(storedValue) : initialValue
);
createEffect(() => {
localStorage.setItem(key, JSON.stringify(value()));
});
return [value, setValue];
}
// Usage
function App() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
);
}
Error Boundaries 🚨
import { ErrorBoundary } from 'solid-js';
function App() {
return (
<ErrorBoundary fallback={err => <div>Error: {err.message}</div>}>
<ComponentThatMightError />
</ErrorBoundary>
);
}
Server-Side Rendering 🖥️
// entry-server.jsx
import { renderToString } from 'solid-js/web';
import App from './App';
export function render() {
return renderToString(() => <App />);
}
Performance Tips 💡
- Use
createMemo
for expensive computations - Implement lazy loading for large components
- Avoid unnecessary component renders
- Use fine-grained reactivity
- Optimize event handlers
- Implement proper code splitting
- Use server-side rendering when needed
- Optimize bundle size
- Use proper TypeScript types
- Follow Solid.js best practices
Best Practices 📝
- Keep components small and focused
- Use TypeScript for better type safety
- Implement proper error handling
- Use stores for global state
- Follow Solid.js conventions
- Write maintainable code
- Use proper event handling
- Implement proper testing
- Follow accessibility guidelines
- Optimize for performance
Additional Resources
Solid.js provides a powerful and efficient way to build modern web applications. Its fine-grained reactivity system and compile-time optimizations result in exceptional performance, making it an excellent choice for building high-performance web applications.