Building the DOM
With the ability to compose the DOM using either functions or type constructors, you can mix and match them to suit your needs.
If building and distributing components or elements, then it is recommended to use the
SolidTypeComponent
- type constructor - syntax.For F# users, this means consumption uses the same DSL for a uniform experience. You also retain the flexibility of optional properties.
For JS consumers, this means consumption as a an XML tag will not miss any arguments (since attributes are packed into the first parameter of a function).
Large vs Small Components
Unlike React, there is negligible consideration as to whether compose smaller components into large components to avoid re-rendering due to the fine-grained reactive system.
Reactivity
Solid-JS reactive system is amazing to work with, but is disjointing if you come from having used React extensively.
Unfortunately, there is no amount of documentation that I could provide which would exceed the work already done on the solid-js website.
I would suggest having a look through their documentation on reactivity.
Happy to answer any specific questions on the community discord if you are running into issues.
[<Erase>]type UnreactiveComponent() =3 collapsed lines
interface RegularNode [<DefaultValue>] val mutable myAttribute: bool [<SolidTypeComponent>] member props.__ = let buttonText = if props.myAttribute then "MyComponent" else "Button" button() { buttonText }8 collapsed lines
[<SolidComponent>]let MyUnreactiveComponentExample() = let sign,setSign = createSignal false div() { button(onClick = (fun _ -> sign() |> not |> setSign)) { "Click me!" } UnreactiveComponent(myAttribute = sign()) }
[<Erase>]type ReactiveComponent() =3 collapsed lines
interface RegularNode [<DefaultValue>] val mutable myAttribute: bool [<SolidTypeComponent>] member props.__ = let buttonText () = if props.myAttribute then "MyComponent" else "Button" button() { buttonText() }8 collapsed lines
[<SolidComponent>]let MyReactiveComponentExample() = let sign,setSign = createSignal false div() { button(onClick = (fun _ -> sign() |> not |> setSign)) { "Click me!" } ReactiveComponent(myAttribute = sign()) }
Compiled Output
export function UnreactiveComponent(props) { const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["myAttribute"]); const buttonText = PARTAS_LOCAL.myAttribute ? "MyComponent" : "Button"; return <button> {buttonText} </button>;}
export function MyUnreactiveComponentExample() { const patternInput = createSignal(false); const sign = patternInput[0]; return <div> <button onClick={(_arg) => { patternInput[1](!sign()); }}> Click me! </button> <UnreactiveComponent myAttribute={sign()} /> </div>;}
export function ReactiveComponent(props) { const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["myAttribute"]); return <button> {PARTAS_LOCAL.myAttribute ? ("MyComponent") : ("Button")} </button>;}
export function MyReactiveComponentExample() { const patternInput = createSignal(false); const sign = patternInput[0]; return <div> <button onClick={(_arg) => { patternInput[1](!sign()); }}> Click me! </button> <ReactiveComponent myAttribute={sign()} /> </div>;}
Conditional Rendering
The Show
component is an explicit version of a conditional ternary, with some additional
benefit in how it is handled by some libraries in the ecosystem.
[<SolidComponent>]let Conditional () = let truthy,setTruthy = createSignal false div() { button(onClick = fun _ -> setTruthy(truthy() |> not)) { "Click me!" } if truthy() then "Boo!" Show(when'=not (truthy())) { "Do you hear that?" } }
export function Conditional() { const patternInput = createSignal(false); const truthy = patternInput[0]; return <div> <button onClick={(_arg) => { patternInput[1](!truthy()); }}> Click me! </button> {truthy() ? ("Boo!") : (undefined)} <Show when={!truthy()}> Do you hear that? </Show> </div>;}
There is a similar Switch
and Match
component for case based rendering.
There is consideration to abstract Switch
and Match
injection when using
pattern matches in CEs.
There is similar consideration to abstract Show
, and Index
/For
.
Handling Streams and Errors
The ErrorBoundary
and Suspense
components are used in handling async
and errors within the DOM. The relevant sections in the solid-js documentation are
suggested reading.
Last updated: 7/9/25, 7:54 PM