SolidJS — fine-grained reactivity
Bez virtual DOM: createSignal, createMemo, createEffect, createStore, Suspense z createResource, SolidStart i porównanie z React.
SolidJS vs React — porównanie konceptów
State, effects, derived state, lifecycle, context i async data — jak te same koncepty działają inaczej w React i SolidJS.
| Koncepcja | React | SolidJS |
|---|---|---|
| State | useState — re-render komponentu | createSignal — fine-grained DOM update |
| Side effects | useEffect z dependency array | createEffect — auto tracking, bez array |
| Derived state | useMemo(() => ..., [deps]) | createMemo(() => ...) — auto deps |
| Lifecycle | useEffect z [] (mount) | onMount + onCleanup |
| Context | createContext + useContext | createContext + useContext (reactive) |
| Async data | useEffect + useState | createResource + Suspense |
Często zadawane pytania
Co to jest SolidJS i jak działa fine-grained reactivity?
SolidJS: framework JavaScript z fine-grained reactivity. Bez virtual DOM — bezpośrednie aktualizacje DOM. Składnia JSX jak React ale inne zachowanie. Ryan Carniato. Fine-grained reactivity: React — re-render komponentu przy zmianie state. Solid — aktualizuj TYLKO konkretny węzeł DOM. Przykład: const [count, setCount] = createSignal(0). return div p{count()}/p button onClick={() => setCount(c => c+1)} /div. Tylko p aktualizuje przy zmianie count. Nie cały komponent. Sygnały (Signals): const [name, setName] = createSignal('Adam'). name() — getter (wywołanie, nie właściwość!). setName('Jan') — setter. Reactive tracking automatyczny. Każde wywołanie name() śledzone w reaktywnym kontekście. Memos (pochodne): const doubled = createMemo(() => count() * 2). Przelicza tylko gdy zależności zmienią. Lazy — nie przelicza jeśli nie odczytany. Effects: createEffect(() => { console.log('count:', count()) }). Uruchamia się automatycznie przy zmianie. Cleanup: return () => clearTimeout(timer). Bez tablicy zależności — automatyczne śledzenie. Stores: createStore dla obiektów. const [state, setState] = createStore({user: {name: 'Adam', age: 30}}). setState('user', 'age', 31). Immer-like API. Nested updates. Porównanie z React: Solid — brak useState re-render. Solid — brak useEffect dependency array. Solid — mniejszy bundle (6KB vs 42KB React+DOM). Solid — szybszy benchmarks (js-framework-benchmark).
Komponenty, props i lifecycle w SolidJS?
Komponenty: funkcje wywoływane RAZ. Nie re-renderują. Setup phase jak konstruktor. const Counter = (props) => { const [count, setCount] = createSignal(0). return button onClick={() => setCount(c => c+1)} {count()} /button }. Props: dostępne reaktywnie. props.name — automatycznie śledzone. Nie destrukturyzuj! (traci reaktywność). splitProps: const [local, others] = splitProps(props, ['class']). Bezpieczna destrukturyzacja. mergeProps: const merged = mergeProps({defaultValue: 0}, props). Default props. children: const Child = (props) => div {props.children} /div. Children.toArray(props.children). Lifecycle: createEffect — po renderze (cleanup support). onMount: onMount(() => { ... }). Odpowiednik useEffect z []. onCleanup: onCleanup(() => { remove listener }). W createEffect lub komponentach. Show komponent: Show when={isLoggedIn()} fallback={Login}. Renderuj warunkowo. Tylko tworzy/niszczy DOM gdy zmienia się warunek. For komponent: For each={items()} fallback={Loading}. {(item, index) => li {item.name} /li}. Nie renderuje ponownie — aktualizuje tylko zmienione. Switch/Match: Switch fallback={Default}. Match when={type() === 'a'} Component /Match. Portal: renderuj poza hierarchią. Dialog, tooltip. Suspense: Suspense fallback={Spinner}. AsyncComponent. createResource dla async data. ErrorBoundary: ochrona przed crashem komponentu.
Async, Resources i Context w SolidJS?
createResource: async data fetching. const [user, {mutate, refetch}] = createResource(userId, fetchUser). userId — source signal (refetch przy zmianie). fetchUser — async function. user() — Accessor. user.loading — boolean. user.error — błąd. Suspense integration automatyczna. Refetch: refetch() — ponowne wywołanie. mutate(newData) — optymistyczna aktualizacja. Deferred loading: resource.state: 'unresolved', 'pending', 'ready', 'refreshing', 'errored'. Lazy loading komponentów: const LazyComp = lazy(() => import('./Heavy')). Suspense + lazy automatycznie. Context: const ThemeContext = createContext('light'). Provider: ThemeContext.Provider value='dark'. Consumer: useContext(ThemeContext). Bez prop drilling. Reactive w kontekście. Reactive stores przez context: const StoreContext = createContext(). Provider value={[state, setState]}. Każdy konsument reaktywny. SolidStart: meta-framework SolidJS. File-based routing (Vinxi pod spodem). Server functions: use server directive. const getUser = async (id) => {use server; return db.getUser(id)}. SSR + streaming. API routes. SolidStart adaptery: Vercel, Netlify, Cloudflare, Node.js. Router: solid-router. Route component. useParams, useSearchParams, useNavigate. Nested routes. Action (createAction): mutacja danych. Form z serverem. useAction hook. Jak Remix actions.
Reactive primitives — tworzenie własnych i zaawansowane wzorce?
Custom primitives: kompozycja istniejących. function createLocalStorage(key, initial) { const [value, setValue] = createSignal(localStorage.getItem(key) ?? initial). createEffect(() => localStorage.setItem(key, value())). return [value, setValue] }. Reaktywny localStorage. Automatyczny cleanup. Batch: batch(() => { setA(1). setB(2) }). Jeden update zamiast dwóch. Optymalizacja. untrack: untrack(() => count()). Odczyt bez śledzenia. W effect — nie dodaj do zależności. on helper: on(source, fn) — explicit dependency. createReaction: lazy effect. Odpal tylko przy śledzeniu. Reactive graph: każdy signal ma subscribers. Memo — zarówno subscriber i publisher. Fine-grained: update propaguje przez graph. Tylko dotknięte węzły. Solid DX tools: solid-devtools (Vite plugin). Reactive graph visualizer. Signal inspector. Time travel debugging. Animacje: @solidjs/motion. Framer Motion port. spring, animate. CSS transitions przez solid. Testing: solid-testing-library. @solidjs/testing-library. Podobne do RTL. render(Component). screen.getByRole. Vitest + jsdom. Solid 2.0 (nadchodzące): Universal reaktywność. Nie tylko DOM. Node.js streams. React Native? Bundle size: Solid — 6KB. Qwik — 1KB (framework). Svelte — 10KB (runtime). React — 42KB (React + ReactDOM). Alpine.js — 16KB. Vue — 34KB.
SolidJS vs React vs Vue — kiedy wybrać fine-grained reactivity?
SolidJS zalety: Najszybszy framework w js-framework-benchmark (prawie). Mały bundle (~6KB). Fine-grained — brak zbędnych re-renderów. React-like JSX — łatwa migracja dla React developerów. TypeScript support pierwszorzędny. Bez virtual DOM overhead. SolidJS wady: Mały ekosystem (React >>>). Mało bibliotek UI (vs shadcn/ui dla React). Komponenty wywoływane raz — błędy dla React developerów (destrukturyzacja props!). Mały rynek pracy. SolidStart wciąż rozwijany. React zalety: Ogromny ekosystem. Next.js / Remix dojrzałe. Mnóstwo bibliotek. Rynek pracy. React 19 + RSC ulepszenia. Vue 3 zalety: Composition API. Mniejszy bundle niż React. Nuxt.js dojrzały. Popularne w Polsce/Europie. Dobry DX. Angular zalety: Korporacyjny standard. Full framework (router, HTTP, forms wbudowane). Signals (Angular 17+). Kiedy Solid: startup, mały team, performance-critical. Nowy projekt bez legacy. Developer-owned stack. Kiedy React: duży team, wiele developerów. Ekosystem krytyczny. Long-term support. Kiedy Vue: Europejski rynek. Poza React/Angular. Nuxt.js dla SSR. Reaktywność porównanie: React useState — component re-render. Vue ref — component re-render. Solid createSignal — fine-grained DOM update. Angular Signals — fine-grained (Angular 17+). Svelte stores — compile-time reaktywność. Zalecenia: Ucz się Solid dla rozumienia reaktywności. Używaj React w produkcji dla ekosystemu.
Powiązane artykuły
Skontaktuj się z nami
Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.
Wyślij zapytanie
Telefon
+48 790 814 814
Pon-Pt: 9:00 - 18:00
adam@fotz.pl
Odpowiadamy w ciągu 24h
Adres
Plac Wolności 16
61-739 Poznań
Godziny pracy
Wolisz porozmawiać?
Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.
Zadzwoń teraz