# Components Components in Solid are just Pascal(Capital) cased functions. Their first argument is an props object and they return real DOM nodes. ```jsx const Parent = () => (
); const Label = props => ( <>
{props.greeting}
{props.children} ); ``` Since all nodes from JSX are actual DOM nodes, the only responsibility of top level Components is appending to the DOM. ## Props Much like React, Vue, Angular, and other frameworks, you can define properties on your components which allow a parent component to pass data to a child component. Here a parent is passing the string "Hello" to the `Label` component via a `greeting` property. ```jsx const Parent = () => (
); ``` In the above example, the value set on `greeting` is static, but we can also set dynamic values. For example: ```jsx const Parent = () => { const [greeting, setGreeting] = createSignal("Hello"); return (
); }; ``` Components can access properties passed to them via a `props` argument. ```jsx const Label = props => ( <>
{props.greeting}
{props.children} ); ``` Unlike in some other frameworks, you cannot use object destructuring on the `props` of a component. This is because the `props` object is, behind the scenes, relies on Object getters to lazily retrieve values. Using object destructuring breaks the reactivity of `props`. This example shows the "correct" way of accessing props in Solid: ```jsx // Here, `props.name` will update like you'd expect const MyComponent = props =>
{props.name}
; ``` This example shows the wrong way of accessing props in Solid: ```jsx // This is bad // Here, `props.name` will not update (i.e. is not reactive) as it is destructured into `name` const MyComponent = ({ name }) =>
{name}
; ``` While the props object looks like a normal object when you use it (and Typescript users will note that it is typed like a normal object), in reality it is reactive--somewhat similar to a Signal. This has a few implications. Because unlike most JSX frameworks, Solid's function components are only executed once (rather than every render cycle), the following example will not work as desired. ```jsx import { createSignal } from "solid-js"; const BasicComponent = props => { const value = props.value || "default"; return
{value}
; }; export default function Form() { const [value, setValue] = createSignal(""); return (
setValue(e.currentTarget.value)} />
); } ``` In this example, what we probably want to happen is for the `BasicComponent` to display the current value typed into the `input`. But, as a reminder, the `BasicComponent` function will only be executed once when the component is initially created. At this time (at creation), `props.value` will equal `''`. This means that `const value` in `BasicComponent` will resolve to `'default'` and never update. While the `props` object is reactive, accessing the props in `const value = props.value || 'default';` is outside the observable scope of Solid, so it isn't automatically re-evaluated when props change. So how can we fix out problem? Well, in general, we need to access `props` somewhere that Solid can observe it. Generally this means inside JSX or inside a `createMemo`, `createEffect`, or thunk(`() => ...`). Here is one solution that works as expected: ```jsx const BasicComponent = props => { return
{props.value || "default"}
; }; ``` This is equivalently can be hoisted into a function: ```jsx const BasicComponent = props => { const value = () => props.value || "default"; return
{value()}
; }; ``` Another option if it is an expensive computation to use `createMemo`. For example: ```jsx const BasicComponent = props => { const value = createMemo(() => props.value || "default"); return
{value()}
; }; ``` Or using a helper ```jsx const BasicComponent = props => { props = mergeProps({ value: "default" }, props); return
{props.value}
; }; ``` As a reminder, the following examples will _not_ work: ```jsx // bad const BasicComponent = props => { const { value: valueProp } = props; const value = createMemo(() => valueProp || "default"); return
{value()}
; }; // bad const BasicComponent = props => { const valueProp = prop.value; const value = createMemo(() => valueProp || "default"); return
{value()}
; }; ``` Solid's Components are the key part of its performance. Solid's approach is "Vanishing" Components made possible by lazy prop evaluation. Instead of evaluating prop expressions immediately and passing in values, execution is deferred until the prop is accessed in the child. In so we defer execution until the last moment typically right in the DOM bindings maximizing performance. This flattens the hierarchy and removes the need to maintain a tree of Components. ```jsx ; // compiles roughly to: // we untrack the component body to isolate it and prevent costly updates untrack(() => Component({ prop1: "static", // dynamic expression so we wrap in a getter get prop2() { return state.dynamic; } }) ); ``` To help maintain reactivity Solid has a couple prop helpers: ```jsx // default props props = mergeProps({ name: "Smith" }, props); // clone props const newProps = mergeProps(props); // merge props props = mergeProps(props, otherProps); // split props into multiple props objects const [local, others] = splitProps(props, ["className"])
``` ## Children Solid handles JSX Children similar to React. A single child is a single value on `props.children` and multiple is an array. Normally you pass them through to the JSX view. However if you want to interact with them the suggested method is the `children` helper which resolves any downstream control flows and returns a memo. ```jsx // single child const Label = (props) =>
Hi, { props.children }
// multi child const List = (props) =>
{props.children}
;
First
{state.expression}
// map children const List = (props) => ; // modify and map children using helper const List = (props) => { // children helper memoizes value and resolves all intermediate reactivity const memo = children(() => props.children); createEffect(() => { const children = memo(); children.forEach((c) => c.classList.add("list-child")) }) return ; ``` **Important:** Solid treats child tags as expensive expressions and wraps them the same way as dynamic reactive expressions. This means they evaluate lazily on `prop` access. Be careful accessing them multiple times or destructuring before the place you would use them in the view. This is because Solid doesn't have luxury of creating Virtual DOM nodes ahead of time then diffing them so resolution of these `props` must be lazy and deliberate. Use `children` helper if you wish to do this as it memoizes them. ## Lifecycle All lifecycles in Solid are tied to the lifecycle of the reactive system. If you wish to perform some side effect on mount or after update use `createEffect` after render has complete: ```jsx import { createSignal, createEffect } from "solid-js"; function Example() { const [count, setCount] = createSignal(0); createEffect(() => { document.title = `You clicked ${count()} times`; }); return (

You clicked {count()} times

); } ``` For convenience if you need to only run it once you can use `onMount` which is the same as `createEffect` but will only run once. Keep in mind Solid's cleanup is independent of this mechanism. So if you aren't reading the DOM you don't need to use these. If you wish to release something on the Component being destroyed, simply wrap in an `onCleanup`. ```jsx const Ticker = () => { const [state, setState] = createState({ count: 0 }), t = setInterval(() => setState({ count: state.count + 1 }), 1000); // remove interval when Component destroyed: onCleanup(() => clearInterval(t)); return
{state.count}
; }; ``` ## Web Components Since change management is independent of code modularization, Solid Templates are sufficient as is to act as Components, or Solid fits easily into other Component structures like Web Components. [Solid Element](https://github.com/solidui/solid/tree/main/packages/solid-element) Provides an out of the box solution for wrapping your Solid Components as Custom Elements.