Solid Cheat Sheet - APIs
Reactive state
In Solid.js, state is tracked inside a reactive root, which registers function calls (even if through a store getter). Effects and memos are later re-evaluated when state is updated. This allows a very precise control of reactivity.
It also means that evaluating reactive state outside of the reactive root, i.e. by destructuring store objects, will result in a loss of reactivity.
GuidecreateSignal
- simple state- tsxconst [getter, setter] = createSignal(initialValue)getter() // reads and tracks the value if inside reactive rootsetter(value) // overwrites the value and triggers state updates
The initial value is optional, createSignal can be typed in TypeScript with a generic.
Docs createMemo
- derived state- tsxconst getter = createMemo((lastValue) => memoizedValue)getter() // reads and tracks the derived value if inside reactive root
Derived memoized state allows you to reduce the times your effects run due to changes.
Docs createResource
- async state- tsxconst [resource, { mutate, refetch }] =createResource(fetcher, options)// orconst [resource, { mutate, refetch }] =createResource(source, fetcher, options)
fetcher()
is a function that receives the output ofsource()
, if given, and returns a Promise that resolves to the value of theresource()
, which also contains the properties loading (boolean
) anderror
(Error | undefined
).mutate(value)
allows overwriting the value andrefetch()
will re-run the last call offetcher()
.
Docs createStore
- state objects- tsxconst [store, setStore] = createStore(initialValue)store.nested.prop // is a getter that will be trackedsetStore('nested', 'prop', value)setStore('list', [2], value)
Creates a reactive store, an object that tracks read access to all (sub-)properties and a versatile setter function to allow fine-grained manipulation.
Docs produce
- local store mutation- tsxsetStore('todos', reconcile(todos))
Allows direct manipulation of the store object like in Immer.
Docs reconcile
- store diffing- tsxsetStore('todos', reconcile(todos))
Diffs store with another immutable version, e.g. from a large API response
Docs unwrap
- returns data without the store- tsxconst unwrappedStore = unwrap(store)
Gets the data out of a store so it is no longer reactive or connected to the setter.
Docs createMutable
- store with settersWraps a store into a proxy with reactive setters, so you can use it like in MobX/Vue.
Docs
Effects
In Solid.js, everything caused by updates inside the reactive system - DOM modifications, calling external libraries and so on - is managed inside effects.
createEffect
- run side effect- tsxcreateEffect((previous) => {return setValue(otherValue())})
Runs a reactive side effect initially and then whenever a tracked state changes after rendering.
Docs onMount
- run side effect on mount- tsxonMount(() => ref.setAttribute(value()))
Runs a side effect only once on mount, regardless of signals used, like an untracked createEffect.
Docs onCleanup
- run side effects on unmount- tsxonCleanup(() => connection.close())
Runs a side effect on unmount (or
dispose()
call of a reactive root created throughcreateRoot()
).
Docs onError
- run side effect on error- tsxonError(() => connection.retry())
Runs a side effect on any error thrown within the reactive root. The effect callback will receive the error as argument.
Docs createDeferred
- defer signal when idleCreates a new signal from an input signal that is deferred until all other side effects are run or an optional timeout is reached.
DocscreateComputed
- effect immediately before renderRuns a side effect like
createEffect()
, but before instead of after rendering.
DocscreateRenderEffect
- effect during renderingLike
createEffect()
, but is called while rendering.
DocscreateReaction
- effect with external tracking- tsxconst track = createReaction(() => { ... })track(() => signal())
Creates an effect that has an external tracking part.
Docs createSelector
- signal only when selected- tsxconst isSelected = createSelector(selectedId)
Creates a conditional signal that only notifies subscribers when entering or exiting their key matching the value.
Docs
Reactive Tracking
Solid.js comes with a collection of tools to put you in control of what state is tracked when and from where.
untrack
- reads without tracking updates- tsxcreateEffect(() => console.log(untrack(a()))
Reads the signal
a()
without the effect being subscribed to changes, while still tracking everything else.
Docs batch
- synchronous updates- tsxcreateEffect(() => batch(() =>setB(setA(value))))
Without batch(), the signal a() would have been updated and only then the signal b(), but using it ensures, that the notification of tracking effects are deferred until both are ready.
Docs on
- explicitly tracks updates- tsxcreateEffect(on(a, (a) => console.log(a, b()))
The first argument is either an array of signal accessors or a single signal accessor to be tracked, the second is a function that receives the value(s) of these tracked signals and won't track any signal inside. It's basically the opposite of
untrack()
.
Docs useTransition
- batch asynchronous updates- tsxconst [pending, start] = useTransition()start(() => setSignal(newValue))
Batches asynchronous updates in a transaction deferring commit until all processes under the same Suspense boundaries are complete.
start(...)
returns a Promise that resolves on completion.
Docs startTransition
- batch asynchronous updates- tsxstartTransition(() => setSignal(newValue))
Like useTransition, just without the pending accessor.
Docs observable
- signal to rxjs observable- tsximport { from } from "rxjs"const [value, setValue] = createSignal(0)from(observable(value)).subscribe(...)
Creates an observable from a signal to be consumed by any observable library like rxjs.
Docs from
- rxjs observable to signal- tsxconst rxValue = from(observable$)
Creates a reactive accessor from rxjs type observables (or anything else with a subscribe method, like a svelte store), only subscribing if the signal is tracked and unsubscribing when its tracking scope is disposed.
Docs
Reactive Scope
Solid.js uses a reactive scope to track the use of reactive state. Every use of a reactive state inside the scope is done through a function call, which registers effects to re-run on updates. Asynchronous calls like
Promise
orEvent
break out of the reactive scope, so Solid.js comes with tools to handle the scope itself.createRoot
- creates tracking context- tsxconst dispose = createRoot((dispose) => {createEffect(...)return dispose})
Creates a reactive scope that can manually unsubscribe all effects through its dispose handler and will return the return value of the scope. Effects will not be able to track signals and stores.
Functions likerender()
automatically create their reactive scope, but you can still usecreateRoot()
inside it to gain manual disposal for your reactive effects.
Docs getOwner
- get the current tracking context- tsxconst scope = getOwner()return <div onClick={(ev) =>runWithOwner(scope, () => props.onClick(ev))}/>
Gets the reactive scope that tracks effects either in order to test its existence or to run effects inside it outside of the current function (e.g. in timeouts or events) by using
runWithOwner()
.
Docs runWithOwner
- runs in tracking context- tsxconst scope = getOwner()return <div onClick={(ev) =>runWithOwner(scope, () => props.onClick(ev))}/>
Runs a callback inside the scope of a reactive root obtained through
getOwner()
, for example to run it inside a timeout or event.
Docs
Reactive Data
Since reactive data like props are often handled by object getters or proxies, destructuring them outside of an effect will break reactivity. Solid.js brings tools to handle them without losing reactivity.
mergeProps
- reactive object merge- tsxconst p = mergeProps(defaults, props)
Shallowly merges all reactive objects together, retaining their reactivity (you can add as many objects as you like).
Docs splitProps
- reactive object splitting- tsxconst [local, rest] = splitProps(props, ["children"])<div {...rest}><span>{local.children}</span></div>
Splits a reactive object into multiple objects while retaining the reactivity of the properties.
Docs mapArray
- reactively maps fixed length arraymaps a reactive array, retaining the reactive properties of the items; otherwise similar to mapArray. Is used by the
<For>
flow control.
DocsindexArray
- reactively maps varying length arraymaps a reactive array, retaining the reactive properties of the indices; items are cached by reference, while the index argument is a signal. The map function itself is not tracking. Is used by the
<Index>
flow control.
Docs
Component APIs
Solid.js comes with a few helpers to manage components internally.
createContext
- state bound to component tree- tsxconst context = createContext(defaultValue)const Consumer = (props) => {const contextValue = useContext(context)}<context.Provider><Consumer /></context.Provider/>
Creates a context object with a provider component to inject dependencies bound to the view to be used with
useContext()
. The default value is optional.
Docs useContext
- use bound state- tsxconst context = createContext(defaultValue)const Consumer = (props) => {const contextValue = useContext(context)}<context.Provider><Consumer /></context.Provider/>
Gets the (default) value of the nearest context provider created with
createContext()
from the given context object.
Docs children
- reactively unwrap children- tsxconst childs = children(() => props.children)
Helper that automatically unwraps children (or other reactive values) that are function elements and memoizes the result in an accessor.
Docs lazy
- unwrap promise containing component- tsxconst AsyncComponent =lazy(import('./AsyncComponent'))return <Suspense fallback="...Loading"><AsyncComponent /></Suspense>
Creates a component from a Promise that can be tracked and replaced with a fallback until resolved in
<Suspense>
.
Docs createUniqueId
- unique ID for components- tsxconst componentId = createUniqueId()
Creates a unique ID that is stable across server and browser to enable synchronization of server-rendered templates in client-side hydration.
Docs
Rendering
Solid.js is very flexible when it comes to rendering both on the server and the client.
render
- applies component to mount point- tsxrender(() => <App />, document.getElementById("root"))
Browser-only method to add a component to a mount point inside its own reactive root.
Docs hydrate
- adds client-side logic to server-rendered html- tsxhydrate(() => <App />, document.getElementById("root"))
Browser-only method to add client-side logic (e.g. event handlers) to server-rendered code.
Docs renderToString
- html string from component- tsxconst html = renderToString(() => <App />)
Creates a static HTML string from a component to be sent to the client and be hydrated using
hydrate()
.
Docs renderToStringAsync
- async renderToString- tsxconst html = await renderToStringAsync(() => <App />)
Creates a static HTML string from a component to be sent to the client and be hydrated using
hydrate()
, but attempts to resolve all async components and resolve all resources.
Docs renderToStream
- render to (node/web) stream- tsxrenderToStream(() => <App />).pipe(res)
Rendering the component asynchronously as string into a stream to be hydrated on the client using
hydrate()
; initial data contains suspense fallback placeholders and everything else will come in once it resolves.
Docs isServer
- true if run in ssr modeis
true
on the server andfalse
in the browser; helpful for tree-shaking.
DocsgenerateHydrationScript
- hydrate SSR components on the serverGenerates hydration script as string to be used on the server.
Docs<HydrationScript />
- hydrate SSR components on the clientGenerates hydration script as a JSX.Component to be used in the client.
Docs
<JSX prop={value}
JSX elements receive attributes separately or with a spread operator:
tsx<Element {...props} />Solid uses a babel plugin to transform JSX to efficient rendering through cloning templates; updates are just side effects within Solid's reactive system.
Guideref
- access DOM element- tsxlet ref!: HTMLDivElement<div ref={ref} />// orlet [ref, setRef] = createSignal<HTMLDivElement>()<div ref={setRef} />
A reference to DOM arrays for intrinsic elements and whatever reference components return (or not). Can be used with a let variable or a setter-style function (or any other function receiving the reference).
Docs classList
- class names from object- tsx<div classList={{ xl: size() === 'xl', box: true }} />
Preferred method of setting and toggling multiple class names using an object with the keys being the class names, and the values being truthy or falsy toggling them. Beware that there might be side effects if using class and classList at the same time.
Docs style
- inline styles (string or object)- tsx<div style="color: red;" /><div style={{ color: 'red '}} />
Attribute to set inline styles and CSS variables, either as a string or from an object.
Docs innerHTML
- directly inject HTMLSet the HTML content (Warning: overwrites child nodes and can lead to security issues if the content is not completely controlled).
DocstextContent
- directly inject TextReplace the content with a text node containing the given text (Warning: may overwrite child nodes)
Docson[event]
- delegated dom eventsDelegated event listeners (using event.currentTarget instead of event.target), only bound once.
Docson:[event]
- direct dom events- tsximport { JSX } from "solid-js"declare module "solid-js" {namespace JSX {interface CustomEvents {MyEvent: Event}}}<div on:MyEvent={handler} />
Native event listener (for typescript, this requires extending the JSX namespace, as shown above)
Docs oncapture:[event]
- capturing dom events- tsximport { JSX } from "solid-js"declare module "solid-js" {namespace JSX {interface CustomCaptureEvents {MyEvent: Event}}}<div oncapture:MyEvent={handler} />
Native event listener with capturing (for typescript, this requires extending the JSX namespace, as shown above)
Docs use:[directive]
- use custom directive- tsximport { JSX } from "solid-js"declare module "solid-js" {namespace JSX {interface Directives {clickOutside: [() => void]}}}<div use:clickOutside={handler} />
Directives are functions that receives the node of the intrinsic element as first and their property as second argument, allowing for elegant code reuse (for typescript, this requires extending the JSX namespace)
Docs prop:[property]
- direct dom property access- tsximport { JSX } from "solid-js"declare module "solid-js" {namespace JSX {interface ExplicitProperties {property: string}}}<div prop:property="foobar" />
Will set the property as property of the intrinsic element instead of an attribute.
Docs attr:[attribute]
- direct dom attribute access- tsximport { JSX } from "solid-js"declare module "solid-js" {namespace JSX {interface ExplicitAttributes {attribute: number}}}<div attr:attribute={2} />
Will set the property as attribute of the intrinsic element instead of a property.
Docs /*@once*/
- untrack for JSX properties- tsx<Component prop={/*@once*/prop.foo} />
Will make sure prop.foo will not be tracked by not converting the assignment to an effect, which is more efficient than untrack.
Docs />{props.children}</JSX>
Children in Solid are typically HTML elements, an array of HTML elements, server rendered elements (Objects with
{ t: template-string }
), strings (TextNodes), false, null or a function returning any of the aforementioned.
JSX Control Flow
Solid comes with control flow components that allow you to express conditional and iterative rendering directly within the JSX.
<Show>
- conditionally show content- tsx<Showwhen={condition()}fallback={<div>Fallback</div>}><Content /></Show>
Renders the children if the condition returns a truthy value, otherwise renders the optional fallback (or nothing as a default).
Docs <Switch>/<Match>
- multiple conditions- tsx<Switch fallback={<div>Fallback</div>}><Match when={conditionA()}><PartA /></Match><Match when={conditionB()}><PartB /></Match></Switch>
Like a switch-Statement, but as a control flow component and with fallback prop instead of a default case.
Docs <For>
- map array items by position- tsx
Will track array items by reference over changing positions; if you expect more changes of positions than changes of content, use
<For>
, otherwise consider using<Index>
.
Docs <Index>
- map array items by value- tsx
Will track array items by content; if you expect content to change rather than changing positions, use
<Index>
, otherwise consider using<For>
.
Docs <Dynamic>
- variable component- tsx<Dynamiccomponent={loggedIn() ? App : Login}user={user()}/>
Returns a component of a variable type, use strings for intrinsic elements or functions for components.
Docs <Portal>
- render elsewhere- tsx
Switch the mount point for the children.
Docs <ErrorBoundary>
- catch errors in components- tsx
Catches errors for the childrens, present a fallback and allows handling the errors and reset the state.
Docs <Suspense>
- fallback for async state- tsx
Shows an optional fallback until the resource promises inside the component (from createResource or lazy) are resolved.
Docs <SuspenseList>
- organize async fallback- tsx
Experimental; allows defining the order in which suspended parts of the layout are replaced with the loaded content in order to avoid layout thrashing.
Docs