W↓
All docs
🔑
Sign Up/Sign In
docs.solidjs.com/reference/
Public Link
Apr 8, 2025, 10:10:16 AM - complete - 101.3 kB
Starting URLs:
https://docs.solidjs.com/reference/basic-reactivity/create-effect
Crawl Prefixes:
https://docs.solidjs.com/reference/
## Page: https://docs.solidjs.com/reference/basic-reactivity/create-effect import { createEffect } from "solid-js"function createEffect<T>(fn: (v: T) => T, value?: T): void Effects are a general way to make arbitrary code ("side effects") run whenever dependencies change, e.g., to modify the DOM manually. `createEffect` creates a new computation that runs the given function in a tracking scope, thus automatically tracking its dependencies, and automatically reruns the function whenever the dependencies update. For example: const [a, setA] = createSignal(initialValue)// effect that depends on signal `a`createEffect(() => doSideEffect(a())) The effect will run whenever `a` changes value. The effect will also run once, immediately after it is created, to initialize the DOM to the correct state. This is called the "mounting" phase. However, we recommend using `onMount` instead, which is a more explicit way to express this. The effect callback can return a value, which will be passed as the `prev` argument to the next invocation of the effect. This is useful for memoizing values that are expensive to compute. For example: const [a, setA] = createSignal(initialValue)// effect that depends on signal `a`createEffect((prevSum) => { // do something with `a` and `prevSum` const sum = a() + b() if (sum !== prevSum) console.log("sum changed to", sum) return sum}, 0)// ^ the initial value of the effect is 0 Effects are meant primarily for side effects that read but don't write to the reactive system: it's best to avoid setting signals in effects, which without care can cause additional rendering or even infinite effect loops. Instead, prefer using createMemo to compute new values that depend on other reactive values, so the reactive system knows what depends on what, and can optimize accordingly. If you do end up setting a signal within an effect, computations subscribed to that signal will be executed only once the effect completes; see `batch` for more detail. The first execution of the effect function is not immediate; it's scheduled to run after the current rendering phase (e.g., after calling the function passed to render, createRoot, or runWithOwner). If you want to wait for the first execution to occur, use queueMicrotask (which runs before the browser renders the DOM) or `await Promise.resolve()` or `setTimeout(..., 0)` (which runs after browser rendering). // assume this code is in a component function, so is part of a rendering phaseconst [count, setCount] = createSignal(0)// this effect prints count at the beginning and when it changescreateEffect(() => console.log("count =", count()))// effect won't run yetconsole.log("hello")setCount(1) // effect still won't run yetsetCount(2) // effect still won't run yetqueueMicrotask(() => { // now `count = 2` will print console.log("microtask") setCount(3) // immediately prints `count = 3` console.log("goodbye")})// --- overall output: ---// hello// count = 2// microtask// count = 3// goodbye This delay in first execution is useful because it means an effect defined in a component scope runs after the JSX returned by the component gets added to the DOM. In particular, refs will already be set. Thus you can use an effect to manipulate the DOM manually, call vanilla JS libraries, or other side effects. Note that the first run of the effect still runs before the browser renders the DOM to the screen (similar to React's `useLayoutEffect`). If you need to wait until after rendering (e.g., to measure the rendering), you can use `await Promise.resolve()` (or `Promise.resolve().then(...)`), but note that subsequent use of reactive state (such as signals) will not trigger the effect to rerun, as tracking is not possible after an async function uses `await`. Thus you should use all dependencies before the promise. If you'd rather an effect run immediately even for its first run, use createRenderEffect or createComputed. You can clean up your side effects in between executions of the effect function by calling onCleanup inside the effect function. Such a cleanup function gets called both in between effect executions and when the effect gets disposed (e.g., the containing component unmounts). For example: // listen to event dynamically given by eventName signalcreateEffect(() => { const event = eventName() const callback = (e) => console.log(e) ref.addEventListener(event, callback) onCleanup(() => ref.removeEventListener(event, callback))}) * * * * `fn` - The function to run in a tracking scope. It can return a value, which will be passed as the `prev` argument to the next invocation of the effect. * `value` - The initial value of the effect. This is useful for memoizing values that are expensive to compute. --- ## Page: https://docs.solidjs.com/reference/basic-reactivity/create-memo Memos let you efficiently use a derived value in many reactive computations. `createMemo` creates a readonly reactive value equal to the return value of the given function and makes sure that function only gets executed when its dependencies change. import { createMemo } from "solid-js"function createMemo<T>( fn: (v: T) => T, value?: T, options?: { equals?: false | ((prev: T, next: T) => boolean) }): () => T Here's an example of how createMemo can be used: const value = createMemo(() => computeExpensiveValue(a(), b()))//read the valuevalue() In Solid, you often don't need to wrap functions in memos; you can alternatively just define and call a regular function to get similar reactive behavior. The main difference is when you call the function in multiple reactive settings. In this case, when the function's dependencies update, the function will get called multiple times unless it is wrapped in createMemo. For example: const user = createMemo(() => searchForUser(username()))// compare with: const user = () => searchForUser(username());return ( <ul> <li>Your name is {user()?.name}</li> <li> Your email is <code>{user()?.email}</code> </li> </ul>) When the username signal updates, searchForUser will get called just once. If the returned user actually changed, the user memo updates, and then both list items will update automatically. If we had instead defined user as a plain function `() => searchForUser(username())`, then `searchForUser` would have been called twice, once when updating each list item. Another key difference is that a memo can shield dependents from updating when the memo's dependencies change but the resulting memo value doesn't. Like createSignal, the derived signal made by `createMemo` updates (and triggers dependents to rerun) only when the value returned by the memo function actually changes from the previous value, according to JavaScript's `===` operator. Alternatively, you can pass an options object with `equals` set to false to always update the memo when its dependencies change, or you can pass your own `equals` function for testing equality. The memo function is called with an argument equal to the value returned from the previous execution of the memo function, or, on the first call, equal to the optional second argument to `createMemo`. This is useful for reducing computations, such as: // track the sum of all values taken on by input() as it updatesconst sum = createMemo((prev) => input() + prev, 0) The memo function should not change other signals by calling setters (it should be "pure"). This enables Solid to optimize the execution order of memo updates according to their dependency graph, so that all memos can update at most once in response to a dependency change. * * * | Name | Type | Description | | --- | --- | --- | | fn | `(v: T) => T` | The function to memoize. | | value | `T` | The initial value of the memo. | | options | `{ equals?: false | ((prev: T, next: T) => boolean) }` | An optional object with an `equals` function to test equality. | --- ## Page: https://docs.solidjs.com/reference/basic-reactivity/create-resource `createResource` takes an asynchronous fetcher function and returns a signal that is updated with the resulting data when the fetcher completes. There are two ways to use `createResource`: you can pass the fetcher function as the sole argument, or you can additionally pass a source signal as the first argument. The source signal will retrigger the fetcher whenever it changes, and its value will be passed to the fetcher. const [data, { mutate, refetch }] = createResource(fetchData) const [data, { mutate, refetch }] = createResource(source, fetchData) In these snippets, the fetcher is the function `fetchData`, and `data()` is undefined until `fetchData` finishes resolving. In the first case, `fetchData` will be called immediately. In the second, `fetchData` will be called as soon as `source` has any value other than false, null, or undefined. It will be called again whenever the value of `source` changes, and that value will always be passed to `fetchData` as its first argument. You can call `mutate` to directly update the `data` signal (it works like any other signal setter). You can also call refetch to rerun the fetcher directly, and pass an optional argument to provide additional info to the fetcher e.g `refetch(info)`. `data` works like a normal signal getter: use `data()` to read the last returned value of `fetchData`. But it also has extra reactive properties: * `data.loading`: whether the fetcher has been called but not returned. * `data.error`: if the request has errored out. `createResource`: provides an `Error` object for `data.error`. It will show even if the fetcher throws something else. * Fetcher throws an `Error` instance, `data.error` will be that instance. * If the fetcher throws a string, `data.error.message` will contain that string. * When the fetcher throws a value that is neither an `Error` nor a string, that value will be available as `data.error.cause`. * As of **v1.4.0**, `data.latest` returns the last value received and will not trigger Suspense or transitions; if no value has been returned yet, `data.latest` will act the same as `data()`. This can be useful if you want to show the out-of-date data while the new data is loading. `loading`, `error`, and `latest` are reactive getters and can be tracked. * * * The `fetcher` is the async function that you provide to `createResource` to actually fetch the data. It is passed two arguments: the value of the source signal (if provided), and an info object with two properties: `value` and `refetching`. The `value` property tells you the previously fetched value. The `refetching` property is true if the `fetcher` was triggered using the refetch function and false otherwise. If the `refetch` function was called with an argument (`refetch(info)`), refetching is set to that argument. async function fetchData(source, { value, refetching }) { // Fetch the data and return a value. //`source` tells you the current value of the source signal; //`value` tells you the last returned value of the fetcher; //`refetching` is true when the fetcher is triggered by calling `refetch()`, // or equal to the optional data passed: `refetch(info)`}const [data, { mutate, refetch }] = createResource(getQuery, fetchData)// read valuedata()// check if loadingdata.loading// check if erroreddata.error// directly set value without creating promisemutate(optimisticValue)// refetch the last request explicitlyrefetch() * * * #### v1.4.0 If you're using `renderToStream`, you can tell Solid to wait for a resource before flushing the stream using the `deferStream` option: // fetches a user and streams content as soon as possibleconst [user] = createResource(() => params.id, fetchUser)// fetches a user but only streams content after this resource has loadedconst [user] = createResource(() => params.id, fetchUser, { deferStream: true,}) #### v1.5.0 1. We've added a new state field which covers a more detailed view of the Resource state beyond `loading` and `error`. You can now check whether a Resource is `unresolved`, `pending`, `ready`, `refreshing`, or `errored`. | State | Value resolved | Loading | Has error | | --- | --- | --- | --- | | `unresolved` | No | No | No | | `pending` | No | Yes | No | | `ready` | Yes | No | No | | `refreshing` | Yes | Yes | No | | `errored` | No | No | Yes | 2. When server-rendering resources, especially when embedding Solid in other systems that fetch data before rendering, you might want to initialize the resource with this prefetched value instead of fetching again and having the resource serialize it in its own state. You can use the new `ssrLoadFrom` option for this. Instead of using the default `server` value, you can pass `initial` and the resource will use `initialValue` as if it were the result of the first fetch for both SSR and hydration. const [data, { mutate, refetch }] = createResource(() => params.id, fetchUser, { initialValue: preloadedData, ssrLoadFrom: "initial",}) 3. Resources can be set with custom defined storage with the same signature as a Signal by using the storage option. For example using a custom reconciling store could be done this way: function createDeepSignal<T>(value: T): Signal<T> { const [store, setStore] = createStore({ value, }) return [ () => store.value, (v: T) => { const unwrapped = unwrap(store.value) typeof v === "function" && (v = v(unwrapped)) setStore("value", reconcile(v)) return store.value }, ] as Signal<T>}const [resource] = createResource(fetcher, { storage: createDeepSignal,}) This option is still experimental and may change in the future. * * * The `createResource` function takes an optional third argument, an options object. The options are: | Name | Type | Default | Description | | --- | --- | --- | --- | | name | `string` | `undefined` | A name for the resource. This is used for debugging purposes. | | deferStream | `boolean` | `false` | If true, Solid will wait for the resource to resolve before flushing the stream. | | initialValue | `any` | `undefined` | The initial value of the resource. | | onHydrated | `function` | `undefined` | A callback that is called when the resource is hydrated. | | ssrLoadFrom | `"server" | "initial"` | `"server"` | The source of the initial value for SSR. If set to `"initial"`, the resource will use the `initialValue` option instead of the value returned by the fetcher. | | storage | `function` | `createSignal` | A function that returns a signal. This can be used to create a custom storage for the resource. This is still experimental | * * * The function and type definitions for `createResource` are as follows: import { createResource } from "solid-js"import type { ResourceReturn, ResourceOptions } from "solid-js"type ResourceReturn<T> = [ { (): T | undefined state: "unresolved" | "pending" | "ready" | "refreshing" | "errored" loading: boolean error: any latest: T | undefined }, { mutate: (v: T | undefined) => T | undefined refetch: (info: unknown) => Promise<T> | T }]type ResourceOptions<T, S = unknown> = { initialValue?: T name?: string deferStream?: boolean ssrLoadFrom?: "initial" | "server" storage?: ( init: T | undefined ) => [Accessor<T | undefined>, Setter<T | undefined>] onHydrated?: (k: S | undefined, info: { value: T | undefined }) => void}function createResource<T, U = true>( fetcher: ( k: U, info: { value: T | undefined; refetching: boolean | unknown } ) => T | Promise<T>, options?: ResourceOptions<T, U>): ResourceReturn<T>function createResource<T, U>( source: U | false | null | (() => U | false | null), fetcher: ( k: U, info: { value: T | undefined; refetching: boolean | unknown } ) => T | Promise<T>, options?: ResourceOptions<T, U>): ResourceReturn<T> --- ## Page: https://docs.solidjs.com/reference/basic-reactivity/create-signal Signals are the most basic reactive primitive. They track a single value (which can be a value of any type) that changes over time. import { createSignal } from "solid-js"function createSignal<T>( initialValue: T, options?: { equals?: false | ((prev: T, next: T) => boolean) name?: string internal?: boolean }): [get: () => T, set: (v: T) => T]// available types for return value of createSignal:import type { Signal, Accessor, Setter } from "solid-js"type Signal<T> = [get: Accessor<T>, set: Setter<T>]type Accessor<T> = () => Ttype Setter<T> = (v: T | ((prev?: T) => T)) => T The Signal's value starts out equal to the passed first argument `initialValue` (or undefined if there are no arguments). The `createSignal` function returns a pair of functions as a two-element array: a getter (or accessor) and a setter. In typical use, you would destructure this array into a named Signal like so: const [count, setCount] = createSignal(0)const [ready, setReady] = createSignal(false) Calling the getter (e.g., `count()` or `ready()`) returns the current value of the Signal. Crucial to automatic dependency tracking, calling the getter within a tracking scope causes the calling function to depend on this Signal, so that function will rerun if the Signal gets updated. Calling the setter (e.g., `setCount(nextCount)` or `setReady(nextReady)`) sets the Signal's value and updates the Signal (triggering dependents to rerun) if the value actually changed (see details below). The setter takes either the new value for the signal or a function that maps the previous value of the signal to a new value as its only argument. The updated value is also returned by the setter. As an example: // read signal's current value, and// depend on signal if in a tracking scope// (but nonreactive outside of a tracking scope):const currentCount = count()// or wrap any computation with a function,// and this function can be used in a tracking scope:const doubledCount = () => 2 * count()// or build a tracking scope and depend on signal:const countDisplay = <div>{count()}</div>// write signal by providing a value:setReady(true)// write signal by providing a function setter:const newCount = setCount((prev) => prev + 1) * * * | Name | Type | Default | Description | | --- | --- | --- | --- | | `equals` | `false | ((prev: T, next: T) => boolean)` | `===` | A function that determines whether the Signal's value has changed. If the function returns true, the Signal's value will not be updated and dependents will not rerun. If the function returns false, the Signal's value will be updated and dependents will rerun. | | `name` | `string` | | A name for the Signal. This is useful for debugging. | | `internal` | `boolean` | `false` | If true, the Signal will not be accessible in the devtools. | ### `equals` The `equals` option can be used to customize the equality check used to determine whether the Signal's value has changed. By default, the equality check is a strict equality check (`===`). If you want to use a different equality check, you can pass a custom function as the `equals` option. The custom function will be called with the previous and next values of the Signal as arguments. If the function returns true, the Signal's value will not be updated and dependents will not rerun. If the function returns false, the Signal's value will be updated and dependents will rerun. const [count, setCount] = createSignal(0, { equals: (prev, next) => prev === next,}) Here are some examples of this option in use: // use { equals: false } to allow modifying object in-place;// normally this wouldn't be seen as an update because the// object has the same identity before and after changeconst [object, setObject] = createSignal({ count: 0 }, { equals: false })setObject((current) => { current.count += 1 current.updated = new Date() return current})// use { equals: false } to create a signal that acts as a trigger without storing a value:const [depend, rerun] = createSignal(undefined, { equals: false })// now calling depend() in a tracking scope// makes that scope rerun whenever rerun() gets called// define equality based on string length:const [myString, setMyString] = createSignal("string", { equals: (newVal, oldVal) => newVal.length === oldVal.length,})setMyString("string") // considered equal to the last value and won't cause updatessetMyString("stranger") // considered different and will cause updates ### `name` The `name` option can be used to give the Signal a name. This is useful for debugging. The name will be displayed in the devtools. const [count, setCount] = createSignal(0, { name: "count" }) ### `internal` The `internal` option can be used to hide the Signal from the devtools. This is useful for Signals that are used internally by a component and should not be exposed to the user. const [count, setCount] = createSignal(0, { internal: true }) --- ## Page: https://docs.solidjs.com/reference/component-apis/children import { children } from "solid-js";import type { JSX, ResolvedChildren } from "solid-js";function children(fn: () => JSX.Element): () => ResolvedChildren The `children` helper is used for more complex interactions with props. When you're not just passing children to another component using `props.children` once in JSX, you should use `children`. Props are normally passed in via a getter for `props.children` in this manner: const resolved = children(() => props.children) The return value is a memo evaluating to the resolved children, which updates whenever the children change. Using this memo instead of accessing `props.children` directly has some important advantages in some scenarios. The underlying issue is that, when you specify component children via JSX, Solid automatically defines `props.children` as a property getter, so that the children are created (in particular, DOM is created) whenever `props.children` gets accessed. Two particular consequences: 1. If you access `props.children` multiple times, the children (and associated DOM) get created multiple times. This is useful if you want the DOM to be duplicated (as DOM nodes can appear in only one parent element), but in many cases it creates redundant DOM nodes. If you instead call `resolved()` multiple times, you re-use the same children. 2. If you access `props.children` outside of a tracking scope (e.g., in an event handler), then you create children that will never be cleaned up. If you instead call `resolved()`, you re-use the already resolved children. You also guarantee that the children are tracked in the current component, as opposed to another tracking scope such as another component. In addition, the `children` helper "resolves" children by calling argumentless functions and flattening arrays of arrays into an array. For example, a child specified with JSX like `{signal() * 2}` gets wrapped into a getter function `() => count() * 2` in `props.children`, but gets evaluated to an actual number in resolved, properly depending on a count signal. If the given `props.children` is not an array (which occurs when the JSX tag has a single child), then the `children` helper will not normalize it into an array. This is useful behavior e.g. when the intention is to pass a single function as a child, which can be detected via `typeof resolved() === 'function'`. If you want to normalize to an array, the returned memo has a `toArray` method _(new in 1.5)_. In most cases, you don't need (and in some cases, don't want) to use the `children` helper if you're just passing `props.children` on to another component or element via JSX: const Wrapper = (props) => { return <div>{props.children}</div>} An important aspect of the `children` helper is that it forces the children to be created and resolved, as it accesses `props.children` immediately. This can be undesirable for conditional rendering, e.g., when using the children within a `<Show>` component. For example, the following code always evaluates the children: const resolved = children(() => props.children)return <Show when={visible()}>{resolved()}</Show> To evaluate the children only when `<Show>` would render them, you can push the call to children inside a component or a function within `<Show>`, which only evaluates its children when `when` condition is true. Another nice workaround is to pass `props.children` to the children helper only when you actually want to evaluate the children: const resolved = children(() => visible() && props.children) --- ## Page: https://docs.solidjs.com/reference/component-apis/create-context Context provides a form of dependency injection in Solid. It is used to save from needing to pass data as props through intermediate components (aka **prop drilling**). This function creates a new context object that can be used with useContext and offers the Provider control flow. The default value is used when no Provider is found above in the hierarchy. * * * To avoid reinstatiating a new context when Hot-Module Replacement (HMR) occurs, it is recommended to use `createContext` in its own module (file). For example: import { createContext } from "solid-js";export const INITIAL_COUNT = 0;const INITIAL_STORE_SETTER = { increment: () => {}, decrement: () => {}};export const CounterContext = createContext([ { count: INITIAL_COUNT }, INITIAL_STORE_SETTER]); With the context created in its own module, you can use to instantiate the context provider. import { createStore } from 'solid-js/store';import { CounterContext, INITIAL_COUNT } from "./counter.ts";export function CounterProvider(props) { const [value, setValue] = createStore({ count: props.initialCount || INITIAL_COUNT }) const counter = [ value, { increment() { setValue("count", currentCount => currentCount + 1) }, decrement() { setValue("count", currentCount => currentCount - 1) }, }, ] return ( <CounterContext.Provider value={counter}> {props.children} </CounterContext.Provider> )} A few imporant notes on how to pass data through the context API: * The value passed to provider is passed to `useContext` as is. * Wrapping as a reactive expression will not work. * You should pass in Signals and Stores directly instead of accessing them in the JSX. To learn how to consume the context, see the useContext documentation and the Context concepts entry. * * * `createContext()` takes an optional "default value" as an argument. If `useContext` is called and there is no corresponding context provider above it in the component hierarchy, then the value passed as `defaultValue` is returned. However, if no `defaultValue` was passed, then `undefined` is returned in this case. Also, `defaultValue` (or `undefined`) is returned if `useContext` is called inside an event callback, as it is then outside of the component hierarchy. This has implications for TS. If no `defaultValue` is passed, then it is possible that `useContext()` will return `undefined`, and the types reflect this. Another (used in the example in the previous section) is provide a default value to `createContext()`. In that case, `useContext()` will always return a value, and therefore TS will not complain either. The pitfall with this approach is that if you _unintentionally_ use `useContext` outside of a provider, it may not be immediately apparent, because the context is still providing a valid value. Therefore, if you expect to always use `useContext` within a provider, it is best to use the error based approach described above. * * * interface Context<T> { id: symbol Provider: (props: { value: T; children: any }) => any defaultValue: T}function createContext<T>(defaultValue?: T): Context<T | undefined> --- ## Page: https://docs.solidjs.com/reference/component-apis/create-unique-id import { createUniqueId } from "solid-js"function createUniqueId(): string A universal id generator that is stable across server/browser. const id = createUniqueId() **Note:** on the server this only works under hydratable components. --- ## Page: https://docs.solidjs.com/reference/component-apis/lazy import { lazy } from "solid-js"import type { Component } from "solid-js"function lazy<T extends Component<any>>( fn: () => Promise<{ default: T }>): T & { preload: () => Promise<T> } Used to lazy load components to allow for code splitting. Components are not loaded until rendered. Lazy loaded components can be used the same as its statically imported counterpart, receiving props etc. Lazy components trigger `<Suspense>` // wrap importconst ComponentA = lazy(() => import("./ComponentA"));// use in JSX<ComponentA title={props.title} /> --- ## Page: https://docs.solidjs.com/reference/component-apis/use-context Used to grab context within a context provider scope to allow for deep passing of props without having to pass them through each Component function. It's therefore used in conjunction with `createContext` to consume the data from a Provider scope and thus avoid passing data through intermediate components (prop drilling). const [state, { increment, decrement }] = useContext(CounterContext) * * * ## Recommended usage It is often a good idea to wrap `useContext` in a function like so: function useCounterContext() { const context = useContext(CounterContext) if (!context) { throw new Error("useCounterContext: cannot find a CounterContext") } return context} See the API reference of createContext the API on how to generate a Provider scope. And check the Context concepts for more information on how to architecture your contexts. * * * ## Type signature import { type Context } from "solid-js"function useContext<T>(context: Context<T>): T --- ## Page: https://docs.solidjs.com/reference/components/dynamic This component lets you insert an arbitrary Component or tag and passes the props through to it. import { Dynamic } from "solid-js/web"import type { JSX } from "solid-js"function Dynamic<T>( props: T & { children?: any component?: Component<T> | string | keyof JSX.IntrinsicElements }): () => JSX.Element Here's an example of how you can use it: <Dynamic component={MyComponent} someProp={state.something} /> * * * ## Props | Name | Type | Description | | --- | --- | --- | | `component` | `Component<T>` | `string` | `keyof JSX.IntrinsicElements` | The component to render. | | `children` | `any` | The children to pass to the component. | | `...` | `T` | Any other props to pass to the component. | --- ## Page: https://docs.solidjs.com/reference/components/error-boundary The `<ErrorBoundary>` component catches errors that occur during the rendering or updating of its children and shows a fallback UI instead. This includes: However, errors occurring outside the rendering process are **not** captured by error boundaries. For instance: `fallback` provides content to display when an error occurs. If a function is passed, it receives two parameters: If there's an error within the `fallback` itself, however, it is not caught by the same `<ErrorBoundary>`. Instead, it will bubble up to any parent error boundaries. import { ErrorBoundary } from "solid-js";import { ErrorProne } from "./components";function Example() { return ( <ErrorBoundary fallback={(error, reset) => ( <div> <p>{error.message}</p> <button onClick={reset}>Try Again</button> </div> )} > <ErrorProne /> </ErrorBoundary> );} --- ## Page: https://docs.solidjs.com/reference/components/for The `<For>` component is used to render a list of items. It is similar to the `.map()` function in JavaScript. import { For } from "solid-js"import type { JSX } from "solid-js"function For<T, U extends JSX.Element>(props: { each: readonly T[] fallback?: JSX.Element children: (item: T, index: () => number) => U}): () => U[] A referentially keyed loop with efficient updating of only changed items. The callback takes the current item as the first argument: <For each={state.list} fallback={<div>Loading...</div>}> {(item) => <div>{item}</div>}</For> The `each` prop can also be a function that returns a list. This is useful for creating a loop that depends on a state value: <For each={stateSignal()}>{(item) => <div>{item}</div>}</For> The optional second argument is an index signal: <For each={state.list} fallback={<div>Loading...</div>}> {(item, index) => ( <div> #{index()} {item} </div> )}</For> * * * | Name | Type | Description | | --- | --- | --- | | `each` | `readonly T[]` | The list of items to render. | | `fallback` | `JSX.Element` | A fallback element to render while the list is loading. | | `children` | `(item: T, index: () => number) => U` | A callback that returns a JSX element for each item in the list. | --- ## Page: https://docs.solidjs.com/reference/components/index-component ComponentsEdit this page Non-keyed list iteration (rendered nodes are keyed to an array index). This is useful when there is no conceptual key, like if the data consists of primitives and it is the index that is fixed rather than the value. import { Index } from "solid-js"import type { JSX } from "solid-js"function Index<T, U extends JSX.Element>(props: { each: readonly T[]; fallback?: JSX.Element; children: (item: () => T, index: number) => U;}): () => U[]; A super simple implementation of this component might look like this: function Index<T, U extends JSX.Element>(props: { each: readonly T[]; fallback?: JSX.Element; children: (item: () => T, index: number) => U;}) { return () => { const [items, setItems] = createSignal(props.each); return props.each.map((_, i) => props.children(() => items()[i], i)); };} Here's a look at the implementation of the `Index` component in Solid: <Index each={state.list} fallback={<div>Loading...</div>}> {(item) => <div>{item()}</div>}</Index> Notice that the item is a signal unlike the `For` component. This is because the `Index` component is not keyed to the item itself but rather the index. Optional second argument is an index number: <Index each={state.list} fallback={<div>Loading...</div>}> {(item, index) => ( <div> #{index} {item()} </div> )}</Index> * * * | Name | Type | Description | | --- | --- | --- | | each | `readonly T[]` | The array to iterate over. | | fallback | `JSX.Element` | Optional fallback element to render while the array is loading. | | children | `(item: () => T, index: number) => U` | The function that renders the children. | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/components/portal ComponentsEdit this page `<Portal>` is a component that allows you to render children into a DOM node that exists outside the DOM hierarchy of the parent component. This is useful when your UI has some elements that need to appear on top of everything else, such as modals and tooltips. import { Portal } from "solid-js/web"import type { JSX } from "solid-js"function Portal(props: { mount?: Node useShadow?: boolean isSVG?: boolean children: JSX.Element}): Text This inserts the element in the mount node. Useful for inserting Modals outside of the page layout. Events still propagate through the component hierarchy, however `<Portal>` will only run on the client and has hydration _disabled_. The portal is mounted in a `<div>` unless the target is the document head. `useShadow` places the element in a Shadow Root for style isolation, and `isSVG` is required if inserting into an SVG element so that the `<div>` is not inserted. <Portal mount={document.getElementById("modal")}> <div>My Content</div></Portal> * * * | Name | Type | Default | Description | | --- | --- | --- | --- | | `mount` | `Node` | document.body | The DOM node to mount the portal in. | | `useShadow` | `boolean` | false | Whether to use a Shadow Root for style isolation. | | `isSVG` | `boolean` | false | Whether the mount node is an SVG element. | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/components/show ComponentsEdit this page The `Show` control flow is used to conditionally render part of the view: it renders children when `when` is truthy, a fallback otherwise. It is similar to the ternary operator `(when ? children : fallback)` but is ideal for templating JSX. import { Show } from "solid-js"import type { JSX } from "solid-js"function Show<T>(props: { when: T | undefined | null | false keyed?: boolean fallback?: JSX.Element children: JSX.Element | ((item: T | Accessor<T>) => JSX.Element)}): () => JSX.Element Here's an example of using the `Show` control flow: <Show when={state.count > 0} fallback={<div>Loading...</div>}> <div>My Content</div></Show> `Show` can also be used as a way of keying blocks to a specific data model. For example the function is re-executed whenever the user model is replaced. <Show when={state.user} fallback={<div>Loading...</div>} keyed> {(user) => <div>{user.firstName}</div>}</Show> If the `keyed` property is not used, the argument of the child function will be an accessor containing the item. <Show when={state.user} fallback={<div>Loading...</div>}> {(user) => <div>{user().firstName}</div>}</Show> * * * | Name | Type | Description | | --- | --- | --- | | `when` | `T | undefined | null | false` | The value to test for truthiness | | `keyed` | `boolean` | Whether to key the block to the value of when | | `fallback` | `JSX.Element` | The fallback to render when the `when` is falsy | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/components/suspense A component that tracks all resources read under it and shows a fallback placeholder state until they are resolved. What makes `Suspense` different than `Show` is that it is non-blocking in the sense that both branches exist at the same time even if not currently in the DOM. This means that the fallback can be rendered while the children are loading. This is useful for loading states and other asynchronous operations. import { Suspense } from "solid-js"import type { JSX } from "solid-js"function Suspense(props: { fallback?: JSX.Element children: JSX.Element}): JSX.Element Here's an example of a `Suspense` component that shows a loading spinner while the `User` component is loading. <Suspense fallback={<LoadingSpinner />}> <AsyncComponent /></Suspense> * * * `<Suspense>` is triggered whenever a resource is read under the suspense boundary, and waits until all resources read under the suspense boundary have resolved. Often, however, you may not want this behavior. For example, if your entire page is wrapped in suspense, you may not want a resource that only populates a certain part of the page to trigger suspense. In that case, you can wrap that resource usage in its own suspense boundary, and the resource will only trigger the closest suspense boundary. For example, in the code below, only the `title()` resource will trigger the top level suspense boundary, and only the `data()` resource will trigger the nested suspense boundary: const MyComponent = () => { const [title] = createResource(async () => { /* fetcher code here */ }) const [data] = createResource(async () => { /* fetcher code here */ }) <Suspense> <h1>{title()}</h1> <Suspense> <DataComponent>{data()}</DataComponent> </Suspense> </Suspense>} * * * To understand the purpose of suspense, let's consider the following code snippets. These snippets will have some drawbacks which we will solve by using suspense. We will also see how it is possible to use `Suspense` yet not reap its benefits. Our example use case is to display a user profile. A naive snippet would look like this: const MyComponentWithOptionalChaining = () => { const [profile] = createResource(async () => { /* fetcher code here */ }) return ( <> <div>{profile()?.name}</div> <div>{profile()?.email}</div> </> )} In this code, `profile()` starts as `undefined`, and when the fetcher code finishes, resolves to an object with `name` and `email` properties. Although the resource has not resolved yet, the two `div`s are already created and attached to the document body, albeit with empty text nodes. Once the resource resolves, the `div`s are updated with the appropriate data. The downside of this approach is that the user is shown an empty component - let's see if we can do better than that in this next snippet: const MyComponentWithShow = () => { const [profile] = createResource(async () => { /* fetcher code here */ }) return ( <Show when={profile()} fallback={<div>fetching user data</div>}> <div>{profile().name}</div> <div>{profile().email}</div> </Show> )} In this snippet, we first show a fallback when the resource hasn't resolved yet, and then switch to showing the profile data once it has. This results in a better user experience. On the other hand, there is a slight downside to this approach. In our first example (using optional chaining), the divs were created immediately, and once the resource resolves all that is needed to be done is to fill in the text of the `div`s. But in our second example (using `<Show>`), the `div`s are only created once the resource has resolved, which means there is more work that needs to be done after the resource has resolved before the data can be shown to the user (of course, in this toy example the amount of DOM work is relatively trivial). We can have the best of both worlds by using <Suspense>: const MyComponentWithSuspense = () => { const [profile] = createResource(async () => { /* fetcher code here */ }) return ( <Suspense fallback={<div>fetching user data</div>}> <div>{profile()?.name}</div> <div>{profile()?.email}</div> </Suspense> )} In this case, the `div`s are created immediately, but instead of being attached to the document body, the fallback is shown. Once the resource resolves, the text in the `div`s is updated, and then they are attached to the document (and the fallback removed). It is important to note that _the execution of the component does not pause_ when using suspense. Instead, when a resource is read under a suspense boundary, it ensures that the nodes are not attached to the document until after the resource has resolved. Suspense allows us to have the best of both worlds: do as much work as we can _before_ the resource resolves, and also show a fallback until then. With this in mind, we can understand that there isn't much gained from suspense in the following code: const MyComponentWithSuspenseAndShow = () => { const [profile] = createResource(async () => { /* fetcher code here */ }) return ( <Suspense fallback={<div>fetching user data</div>}> <Show when={profile()}> <div>{profile().name}</div> <div>{profile().email}</div> </Show> </Suspense> )} In this code, we don't create _any_ DOM nodes inside <Suspense> before the resource resolves, so it is pretty much the same as the second example where we only used `<Show>`. * * * | Name | Type | Description | | --- | --- | --- | | `fallback` | `JSX.Element` | The fallback component to render while the children are loading. | --- ## Page: https://docs.solidjs.com/reference/components/suspense-list SuspenseList allows for coordinating multiple parallel Suspense and SuspenseList components. It controls the order in which content is revealed to reduce layout thrashing and has an option to collapse or hide fallback states. import { SuspenseList } from "solid-js"import type { JSX } from "solid-js"function SuspenseList(props: { children: JSX.Element revealOrder: "forwards" | "backwards" | "together" tail?: "collapsed" | "hidden"}): JSX.Element **Note**: SuspenseList is still in the experimental stage and does not have full `SSR` support. <SuspenseList revealOrder="forwards" tail="collapsed"> <ProfileDetails user={resource.user} /> <Suspense fallback={<h2>Loading posts...</h2>}> <ProfileTimeline posts={resource.posts} /> </Suspense> <Suspense fallback={<h2>Loading fun facts...</h2>}> <ProfileTrivia trivia={resource.trivia} /> </Suspense></SuspenseList> --- ## Page: https://docs.solidjs.com/reference/components/switch-and-match ComponentsEdit this page Useful for when there are more than 2 mutual exclusive conditions. It is a more flexible version of the if-else-if-else-if-else-... chain. import { Switch, Match } from "solid-js"import type { MatchProps, JSX } from "solid-js"function Switch(props: { fallback?: JSX.Element children: JSX.Element}): () => JSX.Elementtype MatchProps<T> = { when: T | undefined | null | false children: JSX.Element | ((item: T) => JSX.Element)}function Match<T>(props: MatchProps<T>) A super simple implementation of this component would be: function Switch(props) { let children = props.children if (!Array.isArray(children)) children = [children] for (let i = 0; i < children.length; i++) { const child = children[i] if (child.props.when) return child } return props.fallback} For example, it can be used to perform basic routing: <Switch fallback={<div>Not Found</div>}> <Match when={state.route === "home"}> <Home /> </Match> <Match when={state.route === "settings"}> <Settings /> </Match></Switch> Match also supports function children to serve as keyed flow. * * * ### Switch | Name | Type | Default | Description | | --- | --- | --- | --- | | `fallback` | `JSX.Element` | `undefined` | The fallback element to render if no `Match` component has a truthy `when` prop. | ### Match | Name | Type | Default | Description | | --- | --- | --- | --- | | `when` | `T | undefined | null | false` | `undefined` | The condition to check. If it is truthy, the `children` will be rendered. | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/once Solid's compiler uses a heuristic for reactive wrapping and lazy evaluation of JSX expressions. Does it contain a function call, a property access, or JSX? If yes we wrap it in a getter when passed to components or in an effect if passed to native elements. Knowing this heuristic and its limitations, we can reduce overhead of things we know will never change by accessing them outside of the JSX. A lone variable will never be wrapped. We can also tell the compiler not to wrap them by starting the expression with a comment decorator `/* @once */`. <MyComponent static={/*@once*/ state.wontUpdate} /> This also works on children. <MyComponent>{/*@once*/ state.wontUpdate}</MyComponent> --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/attr Forces the prop to be treated as an attribute instead of a property. Useful for Web Components where you want to set attributes. <my-element attr:status={props.status} /> info Type definitions are required when using TypeScript. See theTypeScript page for examples. --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/bool `bool:*` controls the presence of an attribute in an element. When the value is `truthy` it adds the `attribute` to the element. Alternatively, when the value is `falsy` it removes the `attribute` from the element. This attribute is most useful for Web Components. <my-element bool:status={prop.value} /> // Assuming `prop.value` is `truthy`, then it becomes<my-element status />// And when `falsy`, then it becomes<my-element /> info Type definitions are required when using TypeScript. See the TypeScript page for examples. --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/classlist Solid offers two ways to set the class of an element: class and classList attributes. First, you can set class=... like any other attribute. For example: // Two static classes<div class="active editing" />// One dynamic class, deleting class attribute if it's not needed<div class={state.active ? 'active' : undefined} />// Two dynamic classes<div class={`${state.active ? 'active' : ''} ${state.currentId === row.id ? 'editing' : ''}`} /> Alternatively, the `classList` pseudo-attribute lets you specify an object, where each key is a class and the value is treated as a boolean representing whether to include that class. For example (matching the last example): <div classList={{ active: state.active, editing: state.currentId === row.id }}/> This example compiles to a render effect that dynamically calls element.classList.toggle to turn each class on or off, only when the corresponding boolean changes. For example, when `state.active` becomes true \[false\], the element gains \[loses\] the `active` class. The value passed into `classList` can be any expression (including a signal getter) that evaluates to an appropriate object. Some examples: // Dynamic class name and value<div classList={{ [className()]: classOn() }} />// Signal class listconst [classes, setClasses] = createSignal({})setClasses((c) => ({ ...c, active: true }))<div classList={classes()} /> It's also possible, but dangerous, to mix class and classList. The main safe situation is when class is set to a static string (or nothing), and classList is reactive. (class could also be set to a static computed value as in `class={baseClass()}`, but then it should appear before any classList pseudo-attributes.) If both class and classList are reactive, you can get unexpected behavior: when the class value changes, Solid sets the entire class attribute, so will overwrite any toggles made by classList. Because classList is a compile-time pseudo-attribute, it does not work in a prop spread like `<div {...props} />` or in `<Dynamic>`. --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/innerhtml The `innerHTML` attribute is equivalent to the `innerHTML` DOM property. This attribute replaces all existing nodes of the element with new nodes generated by parsing the provided string as HTML. caution Using `innerHTML` with unsanitized user-supplied data can introduce security vulnerabilities. --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/on For events with capital letters, listener options, or if you need to attach event handlers directly to a DOM element instead of optimized delegating via the document, use `on:*` in place of `on*`. <div on:DOMContentLoaded={(e) => console.log("Welcome!")} /> This directly attaches an event handler (via `addEventListener`) to the `div`. info New in v1.9.0 An aditional special syntax that allows full control of `capture`, `passive`, `once` and `signal` is an intersection or combination of `EventListenerObject` & `AddEventListenerOptions`, as follows: const handler = { handleEvent(e) { console.log(e) }, once:true, passive:false, capture:true}<div on:wheel={handler} />// or inline<div on:click={{passive:true, handleEvent(e) { console.log("Weeeee!")}}} /> This new syntax replaces the now deprecated `oncapture:` and it's future proof for any posible new event listener options. --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/on_ Event handlers in Solid typically take the form of `onclick` or `onClick` depending on style. <div onClick={(e) => console.log(e.currentTarget)} /> Conceptually, this example attaches a `click` event listener (via `addEventListener`) to the `div`. However, Solid actually handles common UI events that bubble and are composed (such as `click`) at the document level, and then synthetically implements delegation (capturing and bubbling). This improves performance for these common events by reducing the number of event handlers. Note that `onClick` handles the event `click`; in general, event names get mapped to lower case. If you need to work with event names containing capital letters, or use listener options such once, passive, capture see `on:` which attaches event handlers directly (also avoiding fancy delegation via document). Solid also supports passing a two-element array to the event handler to bind a value to the first argument of the event handler. This doesn't use `bind` or create an additional closure, so it is a highly optimized way of delegating events. function handler(itemId, e) { /*...*/}<ul> <For each={state.list}>{(item) => <li onClick={[handler, item.id]} />}</For></ul>; Events are never rebound and the bindings are not reactive, as it is expensive to attach and detach listeners. Since event handlers are called like any other function each time an event fires, there is no need for reactivity; shortcut your handler if desired. // if defined, call it; otherwise don't.<div onClick={() => props.handleClick?.()} /> Note that `onChange` and `onInput` work according to their native behavior (unlike, say, React). `onInput` will fire immediately after the value has changed; for most `<input>` fields, `onChange` will only fire after the field loses focus. The event's `currentTarget` refers to the element that the event was attached to, while `target` gives the element that actually triggered the event (e.g. the user clicked on). --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/prop JSX attributesEdit this page Forces the prop to be treated as a property instead of an attribute. <div prop:scrollTop={props.scrollPos + "px"} /> info Type definitions are required when using TypeScript. See the TypeScript page for examples. Report an issue with this page Previous ← on\* Next ref → --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/ref Refs are a way of getting access to underlying DOM elements in our JSX. While it is true one could just assign an element to a variable, it is more optimal to leave components in the flow of JSX. Refs are assigned at render time but before the elements are connected to the DOM. They come in 2 flavors. // variable assigned directly by reflet myDiv;// use onMount or createEffect to read after connected to the DOMonMount(() => console.log(myDiv));<div ref={myDiv} />// Or, callback function (called before connected to the DOM)<div ref={el => console.log(el)} /> Refs can also be used on Components. They still need to be attached on the other side. function MyComp(props) { return <div ref={props.ref} />}function App() { let myDiv onMount(() => console.log(myDiv.clientWidth)) return <MyComp ref={myDiv} />} --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/style JSX attributesEdit this page Solid's style attribute lets you provide either a CSS string or an object where keys are CSS property names: // string<div style={`color: green; height: ${state.height}px`} />// object<div style={{ color: "green", height: state.height + "px" }}/> Unlike React's style attribute, Solid uses **element.style.setProperty** under the hood. This means you need to use the lower-case, dash-separated version of property names instead of the JavaScript camel-cased version, such as `background-color` rather than `backgroundColor`. This actually leads to better performance and consistency with SSR output. // string<div style={`color: green; background-color: ${state.color}; height: ${state.height}px`} />// object<div style={{ color: "green", "background-color": state.color, height: state.height + "px" }}/> This also means you can set CSS variables! For example: // set css variable<div style={{ "--my-custom-color": state.themeColor }} /> Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/textcontent JSX attributesEdit this page The `textContent` attribute is equivalent to the `textContent` DOM property. This attribute replaces all existing child nodes of the element with a single text node containing the provided string. Using `textContent` can improve performance when the element's children are known to be exclusively text, as it bypasses the generic diffing process. Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/jsx-attributes/use JSX attributesEdit this page These are custom directives. In a sense this is just syntax sugar over ref but allows us to easily attach multiple directives to a single element. A directive is a function with the following signature: function directive(element: Element, accessor: () => any): void Directive functions are called at render time but before being added to the DOM. You can do whatever you'd like in them including create signals, effects, register clean-up etc. const [name, setName] = createSignal("")function model(el, value) { const [field, setField] = value() createRenderEffect(() => (el.value = field())) el.addEventListener("input", (e) => setField(e.target.value))};<input type="text" use:model={[name, setName]} /> To register with TypeScript extend the JSX namespace. declare module "solid-js" { namespace JSX { interface Directives { model: [() => any, (v: any) => any] } }} Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/lifecycle/on-cleanup `onCleanup` registers a cleanup method that executes on disposal and recalculation of the current reactive scope. Can be used anywhere to clean up any side effects left behind by initialization. When used in a Component, it runs when the component is unmounted. When used in reactive contexts, such `createEffect`, `createMemo` or a `createRoot`, it runs when the reactive scope is disposed or refreshed. import { onCleanup } from "solid-js"function onCleanup(fn: () => void): void; Without the `onCleanup` function, the event listener would remain attached to the `document` even after the component is removed from the page. This can cause memory leaks and other issues. import { createSignal, onCleanup } from "solid-js"const Component = () => { const [count, setCount] = createSignal(0); const handleClick = () => setCount((value) => value + 1); document.addEventListener("click", handleClick); /** * Remove the event listener when the component is removed/unmounted from the page. */ onCleanup(() => { document.removeEventListener("click", handleClick); }); return <main>Document has been clicked {count()} times</main>;}; --- ## Page: https://docs.solidjs.com/reference/lifecycle/on-mount Registers a method that runs after initial rendering is done and the elements are mounted to the page. Ideal for using refs and managing other one-time setup. This is an alias for an effect that is non-tracking, meaning that it is equivalent to a `createEffect` with no dependencies. // example that shows how to use onMount to get a reference to an elementimport { onMount } from "solid-js"function MyComponent() { let ref: HTMLButtonElement // when the component is mounted, the button will be disabled onMount(() => { ref.disabled = true }) return <button ref={ref}>Focus me!</button>} --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/batch import { batch } from "solid-js"function batch<T>(fn: () => T): T `batch` is a low-level API that batches updates together. More precisely, `batch(fn)` holds the execution of downstream computations during the `fn` block, executing them all together once the block `fn` returns. Thus, instead of a downstream computation executing after every dependency update, it will update just once at the end of the batch. Batching improves performance by avoiding unnecessary recalculation. Suppose you have a downstream memo `down` that depends on multiple upstream signals `up1`, `up2`, and `up3`: import { createSignal, createMemo, createEffect } from "solid-js"const [up1, setUp1] = createSignal(1)const [up2, setUp2] = createSignal(2)const [up3, setUp3] = createSignal(3)const down = createMemo(() => up1() + up2() + up3())// For illustration, monitor when `down` gets recomputed:createEffect(() => console.log(down())) // outputs 6 If you directly update all of the upstream signals outside of batch mode, then `down` will recompute every time. setUp1(4) // recomputes down, outputs 9setUp2(5) // recomputes down, outputs 12setUp3(6) // recomputes down, outputs 15 If instead you update the upstream signals within a `batch`, then `down` will update only once at the end: batch(() => { setUp1(10) // doesn't update down yet setUp2(10) // doesn't update down yet setUp3(10) // doesn't update down yet}) // recomputes down, outputs 30 The impact is even more dramatic if you have _m_ downstream computations (memos, effects, etc.) that each depends on _n_ upstream signals. Without batching, modifying all _n_ upstream signals would cause _m n_ updates to the downstream computations. With batching, modifying all _n_ upstream signals would cause _m_ updates to the downstream computations. Given that each update takes at least _n_ time (just to read the upstream signals), this cost savings can be significant. Batching is also especially helpful when the downstream effects include DOM updates, which can be expensive. Solid uses `batch` internally to automatically batch updates for you in a few cases: * Within `createEffect` and `onMount` (unless they are outside a root) * Within the setter of a store (which can update several properties at once) * Within array methods (e.g. `Array.prototype.splice`) of a mutable store (which can update several elements at once) These save you from having to use `batch` yourself in many cases. For the most part, automatic batching should be transparent to you, because accessing a signal or memo will cause it to update if it is out of date (as of Solid 1.4). For example: batch(() => { setUp1(11) // doesn't update down yet setUp2(11) // doesn't update down yet setUp3(11) // doesn't update down yet console.log(down()) // recomputes down, outputs 33 setUp1(12) // doesn't update down yet setUp2(12) // doesn't update down yet setUp3(12) // doesn't update down yet}) // recomputes down, outputs 36 You can think of `batch(fn)` as setting a global "batch mode" variable, calling the function `fn`, and then restoring the global variable to its previous value. This means that you can nest `batch` calls, and they will form one big batch. It also means that, if `fn` is asynchronous, only the updates before the first `await` will be batched. --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/catch-error info New in v1.7.0 import { catchError } from "solid-js"function catchError<T>(tryFn: () => T, onError: (err: any) => void): T Wraps a `tryFn` with an error handler that fires if an error occurs below that point. Only the nearest scope error handlers execute. Rethrow to trigger up the line. --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/create-root import { createRoot } from "solid-js"function createRoot<T>(fn: (dispose: () => void) => T): T Creates a new non-tracked owner scope that doesn't auto-dispose. This is useful for nested reactive scopes that you do not wish to release when the parent re-evaluates. All Solid code should be wrapped in one of these top level as they ensure that all memory/computations are freed up. Normally you do not need to worry about this as createRoot is embedded into all render entry functions. --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/from Reactive utilitiesEdit this page import { from } from "solid-js"function from<T>( producer: | ((setter: (v: T) => T) => () => void) | { subscribe: ( fn: (v: T) => void ) => (() => void) | { unsubscribe: () => void } }): () => T | undefined A helper to make it easier to interop with external producers like RxJS observables or with Svelte Stores. This basically turns any subscribable (object with a subscribe method) into a Signal and manages subscription and disposal. const signal = from(obsv$) It can also take a custom producer function where the function is passed a setter function that returns an unsubscribe function: const clock = from((set) => { const interval = setInterval(() => { set((v) => v + 1) }, 1000) return () => clearInterval(interval)}) * * * | Name | Type | Description | | --- | --- | --- | | producer | `((setter: (v: T) => T) => () => void) | { subscribe: (fn: (v: T) => void) => (() => void) | { unsubscribe: () => void }; }` | The producer function or subscribable object | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/get-owner import { getOwner } from "solid-js"import type { Owner } from "solid-js"function getOwner(): Owner Gets the reactive scope that owns the currently running code, e.g., for passing into a later call to `runWithOwner` outside of the current scope. Internally, computations (effects, memos, etc.) create owners which are children of their owner, all the way up to the root owner created by `createRoot` or `render`. In particular, this ownership tree lets Solid automatically clean up a disposed computation by traversing its subtree and calling all `onCleanup` callbacks. For example, when a createEffect's dependencies change, the effect calls all descendant `onCleanup` callbacks before running the effect function again. Calling `getOwner` returns the current owner node that is responsible for disposal of the current execution block. Components are not computations, so do not create an owner node, but they are typically rendered from a `createEffect` which does, so the result is similar: when a component gets unmounted, all descendant `onCleanup` callbacks get called. Calling `getOwner` from a component scope returns the owner that is responsible for rendering and unmounting that component. Note that the owning reactive scope isn't necessarily tracking. For example, untrack turns off tracking for the duration of a function (without creating a new reactive scope), as do components created via JSX (`<Component ...>`). --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/index-array import { indexArray } from "solid-js"function indexArray<T, U>( list: () => readonly T[], mapFn: (v: () => T, i: number) => U): () => U[] Similar to `mapArray` except it maps by index. The item is a signal and the index is now the constant. Underlying helper for the `<Index>` control flow. const mapped = indexArray(source, (model) => { return { get id() { return model().id } get firstInitial() { return model().firstName[0]; }, get fullName() { return `${model().firstName} ${model().lastName}`; }, }}); * * * ## Arguments | Name | Type | Description | | --- | --- | --- | | list | `() => readonly T[]` | The list to map. | | mapFn | `(v: () => T, i: number) => U` | The mapping function. | --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/map-array import { mapArray } from "solid-js"function mapArray<T, U>( list: () => readonly T[], mapFn: (v: T, i: () => number) => U): () => U[] Reactive map helper that caches each item by reference to reduce unnecessary mapping on updates. It only runs the mapping function once per value and then moves or removes it as needed. The index argument is a signal. The map function itself is not tracking. Underlying helper for the `<For>` control flow. const mapped = mapArray(source, (model) => { const [name, setName] = createSignal(model.name) const [description, setDescription] = createSignal(model.description) return { id: model.id, get name() { return name() }, get description() { return description() }, setName, setDescription, }}) --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/merge-props A reactive object **merge** method. Useful for setting default props for components in case caller doesn't provide them. Or cloning the props object including reactive properties. This method works by using a proxy and resolving properties in reverse order. This allows for dynamic tracking of properties that aren't present when the prop object is first merged. // default propsprops = mergeProps({ name: "Smith" }, props)// clone propsnewProps = mergeProps(props)// merge propsprops = mergeProps(props, otherProps) --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/observable import { observable } from "solid-js"function observable<T>(input: () => T): Observable<T> This method takes a signal and produces an Observable. You can consume it from another Observable library of your choice, typically with the `from` operator. // How to integrate rxjs with a Solid signalimport { observable } from "solid-js"import { from } from "rxjs"const [s, set] = createSignal(0)const obsv$ = from(observable(s))obsv$.subscribe((v) => console.log(v)) You can also use `from` without rxjs; check out this page. --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/on-util import { on } from "solid-js"function on<T extends Array<() => any> | (() => any), U>( deps: T, fn: (input: T, prevInput: T, prevValue?: U) => U, options: { defer?: boolean } = {}): (prevValue?: U) => U | undefined `on` is designed to be passed into a computation to make its dependencies explicit. If an array of dependencies is passed, `input` and `prevInput` are arrays. createEffect(on(a, (v) => console.log(v, b())));// is equivalent to:createEffect(() => { const v = a(); untrack(() => console.log(v, b()));}); You can also not run the computation immediately and instead opt in for it to only run on change by setting the defer option to true. // doesn't run immediatelycreateEffect(on(a, (v) => console.log(v), { defer: true }));setA("new"); // now it runs * * * const [state, setState] = createStore({ a: 1, b: 2 });// this will not workcreateEffect(on(state.a, (v) => console.log(v)));setState({ a: 3 }); // logs nothing// instead, use an arrow functioncreateEffect( on( () => state.a, (v) => console.log(v) ));setState({ a: 4 }); // logs 4 * * * | Argument | Type | Description | | --- | --- | --- | | deps | `T` | The dependencies to watch. | | fn | `(input: T, prevInput: T, prevValue?: U) => U` | The function to run when the dependencies change. | | options | `{ defer?: boolean }` | Options to configure the effect. | --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/run-with-owner import { runWithOwner } from "solid-js"import type { Owner } from "solid-js"function runWithOwner<T>(owner: Owner, fn: (() => void) => T): T Executes the given function under the provided owner, instead of (and without affecting) the owner of the outer scope. By default, computations created by `createEffect`, `createMemo`, etc. are owned by the owner of the currently executing code (the return value of `getOwner`), so in particular these will get disposed when their owner does. Calling `runWithOwner` provides a way to override this default to a manually specified owner (typically, the return value from a previous call to `getOwner`), enabling more precise control of when computations get disposed. Having a (correct) owner is important for two reasons: * Computations without an owner cannot be cleaned up. For example, if you call `createEffect` without an owner (e.g., in the global scope), the effect will continue running forever, instead of being disposed when its owner gets disposed. * `useContext` obtains context by walking up the owner tree to find the nearest ancestor providing the desired context. So without an owner you cannot look up any provided context (and with the wrong owner, you might obtain the wrong context). Manually setting the owner is especially helpful when doing reactivity outside of any owner scope. In particular, asynchronous computation (via either `async` functions or callbacks like `setTimeout`) lose their automatically set owner, so remembering the original owner via `getOwner` and restoring it via `runWithOwner` is necessary in these cases. For example: const owner = getOwner()setTimeout(() => { // This callback gets run without owner. // Restore owner via runWithOwner: runWithOwner(owner, () => { const foo = useContext(FooContext) createEffect(() => { console.log(foo) }) })}, 1000) **Note:** that owners are not what determines dependency tracking, so `runWithOwner` does not help with tracking in asynchronous functions; use of reactive state in the asynchronous part (e.g. after the first `await`) will not be tracked as a dependency. --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/split-props import { splitProps } from "solid-js"function splitProps<T>( props: T, ...keys: Array<(keyof T)[]>): [...parts: Partial<T>] Splits a reactive object by keys. It takes a reactive object and any number of arrays of keys; for each array of keys, it will return a reactive object with just those properties of the original object. The last reactive object in the returned array will have any leftover properties of the original object. This can be useful if you want to consume a subset of props and pass the rest to a child. function MyComponent(props) { const [local, others] = splitProps(props, ["children"]) return ( <> <div>{local.children}</div> <Child {...others} /> </> )} Because `splitProps` takes any number of arrays, we can split a props object as much as we wish (if, for example, we had multiple child components that each required a subset of the props). Let's say a component was passed six props: ;<MyComponent a={1} b={2} c={3} d={4} e={5} foo="bar" />// ...function MyComponent(props) { console.log(props) // {a: 1, b: 2, c: 3, d: 4, e: 5, foo: "bar"} const [vowels, consonants, leftovers] = splitProps( props, ["a", "e"], ["b", "c", "d"] ) console.log(vowels) // {a: 1, e: 5} console.log(consonants) // {b: 2, c: 3, d: 4} console.log(leftovers.foo) // bar} --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/start-transition import { startTransition } from "solid-js"function startTransition: (fn: () => void) => Promise<void> Similar to `useTransition` except there is no associated pending state. This one can just be used directly to start the Transition. --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/untrack Ignores tracking any of the dependencies in the executing code block and returns the value. This helper is useful when a certain `prop` will never update and thus it is ok to use it outside of the reactive context. import { untrack } from "solid-js"export function Component(props) { const value = untrack(() => props.value) return <div>{value}</div> }} * * * ## Initial and Default Values It is not necessary to manually untrack values that are suppose to serve as a default or initial value to a signal. Even with the linter configured to enforce tracking, the linter will accept it when a `prop` is prefixed with `default` or `initial` as it is a common pattern to use them as such. // component.tsximport { createSignal } from "solid-js"export function Component(props) { const [name, setName] = createSignal(props.initialName) return <div>{name()}</div> }} // component.tsximport { createSignal } from "solid-js"export function Component(props) { const [name, setName] = createSignal(props.defaultName) return <div>{name()}</div> }} --- ## Page: https://docs.solidjs.com/reference/reactive-utilities/use-transition import { useTransition } from "solid-js"function useTransition(): [ pending: () => boolean, startTransition: (fn: () => void) => Promise<void>] Used to batch async updates in a transaction deferring commit until all async processes are complete. This is tied into Suspense and only tracks resources read under Suspense boundaries. const [isPending, start] = useTransition();// check if transitioningisPending();// wrap in transitionstart(() => setSignal(newValue), () => /* transition is done */) --- ## Page: https://docs.solidjs.com/reference/rendering/dev import { DEV } from "solid-js"const DEV: object | undefined On the client, Solid provides (via conditional exports) different builds depending on whether the **development** condition is set. Development mode provides some additional checking — e.g. detecting accidental use of multiple instances of Solid — which are removed in production builds. If you want code to run only in development mode (most useful in libraries), you can check whether the **DEV** export is defined. Note that it is always defined on the server, so you may want to combine with isServer: --- ## Page: https://docs.solidjs.com/reference/rendering/hydrate import { hydrate } from "solid-js/web"import type { JSX } from "solid-js"import type { MountableElement } from "solid-js/web"function hydrate( fn: () => JSX.Element, node: MountableElement, options?: { renderId?: string; owner?: unknown }): () => void This method is similar to `render` except that it attempts to rehydrate what is already rendered to the DOM. When initializing in the browser a page has already been server rendered. const dispose = hydrate(App, document.getElementById("app")) * * * ## Parameters | Prop | type | description | | --- | --- | --- | | fn | `() => JSX.Element` | Function that returns the application code. | | node | MountableElement | DOM Element to mount the application to | | options.renderId | string | | | options.owner | unknown | | --- ## Page: https://docs.solidjs.com/reference/rendering/hydration-script import { generateHydrationScript, HydrationScript } from "solid-js/web"import type { JSX } from "solid-js"function generateHydrationScript(options: { nonce?: string eventNames?: string[]}): stringfunction HydrationScript(props: { nonce?: string eventNames?: string[]}): JSX.Element Hydration Script is a special script that should be placed once on the page to bootstrap hydration before Solid's runtime has loaded. It comes both as a function that can be called and inserted in an HTML string, or as a Component if you are rendering JSX from the `<html>` tag. The options are for the **nonce** to be put on the script tag and any event names for that Solid should capture before scripts have loaded and replay during hydration. These events are limited to those that Solid delegates which include most UI Events that are composed and bubble. By default it is only click and input events. --- ## Page: https://docs.solidjs.com/reference/rendering/is-server import { isServer } from "solid-js/web"const isServer: boolean This indicates that the code is being run as the server or browser bundle. As the underlying runtimes export this as a constant boolean it allows bundlers to eliminate the code and their used imports from the respective bundles. import { isServer } from "solid-js/web";if (isServer) { // I will never make it to the browser bundle} else { // won't be run on the server;} --- ## Page: https://docs.solidjs.com/reference/rendering/render RenderingEdit this page import { render } from "solid-js/web"import type { JSX } from "solid-js"import type { MountableElement } from "solid-js/web"function render( code: () => JSX.Element, element: MountableElement): () => void This is the browser app entry point. Provide a top-level component function and an element to mount to. It is recommended this element be empty: while `render` will just append children, the returned dispose function will remove all children. const dispose = render(App, document.getElementById("app"))// orconst dispose = render(() => <App />, document.getElementById("app")) It's important that the first argument is a function: do not pass JSX directly (as in `render(<App/>, ...)`), because this will call App before render can set up a root to track signal dependencies within App. * * * | Argument | Type | Description | | --- | --- | --- | | code | `() => JSX.Element` | Function that returns the application code. | | element | MountableElement | DOM Element to mount the application to | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/rendering/render-to-stream import { renderToStream } from "solid-js/web"function renderToStream<T>( fn: () => T, options?: { nonce?: string renderId?: string onCompleteShell?: () => void onCompleteAll?: () => void }): { pipe: (writable: { write: (v: string) => void }) => void pipeTo: (writable: WritableStream) => void} This method renders to a stream. It renders the content synchronously including any Suspense fallback placeholders, and then continues to stream the data and HTML from any async resource as it completes. // noderenderToStream(App).pipe(res)// web streamconst { readable, writable } = new TransformStream()renderToStream(App).pipeTo(writable) `onCompleteShell` fires when synchronous rendering is complete before writing the first flush to the stream out to the browser. `onCompleteAll` is called when all server Suspense boundaries have settled. `renderId` is used to namespace renders when having multiple top level roots. --- ## Page: https://docs.solidjs.com/reference/rendering/render-to-string import { renderToString } from "solid-js/web"function renderToString<T>( fn: () => T, options?: { nonce?: string renderId?: string }): string Renders to a string synchronously. The function also generates a script tag for progressive hydration. Options include eventNames to listen to before the page loads and play back on hydration, and nonce to put on the script tag. `renderId` is used to namespace renders when having multiple top level roots. const html = renderToString(App) * * * ## Options | Name | Type | Description | | --- | --- | --- | | `nonce` | `string` | The nonce to use for the script tag. | | `renderId` | `string` | The id to use for the script tag. | --- ## Page: https://docs.solidjs.com/reference/rendering/render-to-string-async import { renderToStringAsync } from "solid-js/web"function renderToStringAsync<T>( fn: () => T, options?: { timeoutMs?: number renderId?: string nonce?: string }): Promise<string> Same as `renderToString` except that it will wait for all `<Suspense>` boundaries to resolve before returning the results. Resource data is automatically serialized into the script tag and will be hydrated on client load. `renderId` is used to namespace renders when having multiple top level roots. const html = await renderToStringAsync(App) * * * ## Options | Name | Type | Description | | --- | --- | --- | | `timeoutMs` | `number` | The number of milliseconds to wait for a `<Suspense>` boundary to resolve before timing out. | | `renderId` | `string` | The id to use for the render. | | `nonce` | `string` | The nonce to use for the script tag. | --- ## Page: https://docs.solidjs.com/reference/secondary-primitives/create-computed import { createComputed } from "solid-js"function createComputed<T>(fn: (v: T) => T, value?: T): void `createComputed` creates a new computation that immediately runs the given function in a tracking scope, thus automatically tracking its dependencies, and automatically reruns the function whenever the dependencies changes. The function gets called with an argument equal to the value returned from the function's last execution, or on the first call, equal to the optional second argument to `createComputed`. Note that the return value of the function is not otherwise exposed; in particular, createComputed has no return value. `createComputed` is the most immediate form of reactivity in Solid, and is most useful for building other reactive primitives. For example, some other Solid primitives are built from `createComputed`. However, it should be used with care, as `createComputed` can easily cause more unnecessary updates than other reactive primitives. Before using it, consider the closely related primitives `createMemo` and `createRenderEffect`. Like `createMemo`, `createComputed` calls its function immediately on updates (unless you're in a batch, effect, or transition). However, while `createMemo` functions should be pure (not set any signals), `createComputed` functions can set signals. Related, `createMemo` offers a readonly signal for the return value of the function, whereas to do the same with `createComputed` you would need to set a signal within the function. If it is possible to use pure functions and `createMemo`, this is likely more efficient, as Solid optimizes the execution order of memo updates, whereas updating a signal within `createComputed` will immediately trigger reactive updates some of which may turn out to be unnecessary. * * * | Name | Type | Description | | --- | --- | --- | | `fn` | `(v: T) => T` | The function to run in a tracking scope. | | `value` | `T` | The initial value to pass to the function. | --- ## Page: https://docs.solidjs.com/reference/secondary-primitives/create-deferred import { createDeferred } from "solid-js"function createDeferred<T>( source: () => T, options?: { timeoutMs?: number equals?: false | ((prev: T, next: T) => boolean) name?: string }): () => T Creates a readonly that only notifies downstream changes when the browser is idle. `timeoutMs` is the maximum time to wait before forcing the update. * * * ## Options | Name | Type | Description | | --- | --- | --- | | timeoutMs | `number` | The maximum time to wait before forcing the update. | | equals | `false or ((prev: T, next: T) => boolean)` | A function that returns true if the value has changed. | | name | `string` | The name of the readonly. | --- ## Page: https://docs.solidjs.com/reference/secondary-primitives/create-reaction import { createReaction } from "solid-js"function createReaction(onInvalidate: () => void): (fn: () => void) => void Sometimes it is useful to separate tracking from re-execution. This primitive registers a side effect that is run the first time the expression wrapped by the returned tracking function is notified of a change. const [s, set] = createSignal("start")const track = createReaction(() => console.log("something"))// run the reaction next time `s` changes.track(() => s())set("end") // "something"set("final") // no-op since the reaction only runs on the first update, need to call `track` again. --- ## Page: https://docs.solidjs.com/reference/secondary-primitives/create-render-effect import { createRenderEffect } from "solid-js"function createRenderEffect<T>(fn: (v: T) => T, value?: T): void A render effect is a computation similar to a regular effect (as created by `createEffect`), but differs in when Solid schedules the first execution of the effect function. While `createEffect` waits for the current rendering phase to be complete, `createRenderEffect` immediately calls the function. Thus the effect runs as DOM elements are being created and updated, but possibly before specific elements of interest have been created, and probably before those elements have been connected to the document. In particular, **refs** will not be set before the initial effect call. Indeed, Solid uses `createRenderEffect` to implement the rendering phase itself, including setting of **refs**. Reactive updates to render effects are identical to effects: they queue up in response to a reactive change (e.g., a single signal update, or a batch of changes, or collective changes during an entire render phase) and run in a single `batch` afterward (together with effects). In particular, all signal updates within a render effect are batched. Here is an example of the behavior. (Compare with the example in `createEffect`.) // assume this code is in a component function, so is part of a rendering phaseconst [count, setCount] = createSignal(0)// this effect prints count at the beginning and when it changescreateRenderEffect(() => console.log("count =", count()))// render effect runs immediately, printing `count = 0`console.log("hello")setCount(1) // effect won't run yetsetCount(2) // effect won't run yetqueueMicrotask(() => { // now `count = 2` will print console.log("microtask") setCount(3) // immediately prints `count = 3` console.log("goodbye")})// --- overall output: ---// count = 0 [this is the only added line compared to createEffect]// hello// count = 2// microtask// count = 3// goodbye Just like `createEffect`, the effect function gets called with an argument equal to the value returned from the effect function's last execution, or on the first call, equal to the optional second argument of `createRenderEffect`. * * * | Name | Type | Description | | --- | --- | --- | | `fn` | `(v: T) => T` | The effect function to be called. | | `value` | `T` | The initial value to be passed to the effect function. | --- ## Page: https://docs.solidjs.com/reference/secondary-primitives/create-selector import { createSelector } from "solid-js"function createSelector<T, U>( source: () => T, fn?: (a: U, b: T) => boolean): (key: U) => boolean Creates a parameterized derived boolean signal `selector(key)` that indicates whether `key` is equal to the current value of the `source` signal. These signals are optimized to notify each subscriber only when their `key` starts or stops matching the reactive `source` value (instead of every time `key` changes). If you have _n_ different subscribers with different keys, and the `source` value changes from `a` to `b`, then instead of all _n_ subscribers updating, at most two subscribers will update: the signal with key `a` will change to `false`, and the signal with key `b` will change to `true`. Thus it reduces from _n_ updates to 2 updates. Useful for defining the selection state of several selectable elements. For example: const [selectedId, setSelectedId] = createSignal()const isSelected = createSelector(selectedId)<For each={list()}> {(item) => <li classList={{ active: isSelected(item.id) }}>{item.name}</li>}</For> In the code above, each `li` element receives an `active` class exactly when the corresponding `item.id` is equal to `selectedId()`. When the `selectedId` signal changes, the `li` element(s) that previously had previously matching `id` get the `active` class removed, and the `li` element(s) that now have a matching `id` get the `active` class added. All other `li` elements get skipped, so if `id`s are distinct, only 2 DOM operations get performed. By contrast, the following code would perform `list().length` DOM operations every time the `selectedId` signal changes: const [selectedId, setSelectedId] = createSignal()<For each={list()}> {(item) => <li classList={{ active: selectedId() === item.id }}>{item.name}</li>}</For> * * * | Name | Type | Description | | --- | --- | --- | | `source` | `() => T` | The source signal to get the value from and compare with keys. | | `fn` | `(a: U, b: T) => boolean` | A function to compare the key and the value, returning whether they should be treated as equal. Default: `===` | --- ## Page: https://docs.solidjs.com/reference/store-utilities/create-mutable Store utilitiesEdit this page `createMutable` creates a new mutable Store proxy object that provides a way to selectively trigger updates only when values change. By intercepting property access, it allows automatic tracking of deep nesting via proxy making it useful for integrating external systems or serving as a compatibility layer with frameworks like MobX or Vue. import { createMutable } from "solid-js/store"import type { Store, StoreNode } from "solid-js/store"function createMutable<T extends StoreNode>(state: T | Store<T>): Store<T>; import { createMutable } from "solid-js/store"const state = createMutable({ someValue: 0, list: [],});// read valuestate.someValue;// set valuestate.someValue = 5;state.list.push(anotherValue); Mutables support setters along with getters. const user = createMutable({ firstName: "John", lastName: "Smith", get fullName() { return `${this.firstName} ${this.lastName}`; }, set setFullName(value) { [this.firstName, this.lastName] = value.split(" "); },}); Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/store-utilities/create-store Stores were intentionally designed to manage data structures like objects and arrays but are capable of handling other data types, such as strings and numbers. * * * import { createStore } from "solid-js/store"import type { StoreNode, Store, SetStoreFunction } from "solid-js/store"function createStore<T extends StoreNode>( state: T | Store<T>): [get: Store<T>, set: SetStoreFunction<T>];type Store<T> = T; // conceptually readonly, but not typed as such * * * import { createStore } from "solid-js/store";// Initialize storeconst [store, setStore] = createStore({ userCount: 3, users: [ { id: 0, username: "felix909", location: "England", loggedIn: false, }, { id: 1, username: "tracy634", location: "Canada", loggedIn: true, }, { id: 1, username: "johny123", location: "India", loggedIn: true, }, ],}); * * * Store objects support the use of getters to store derived values. const [state, setState] = createStore({ user: { firstName: "John", lastName: "Smith", get fullName() { return `${this.firstName} ${this.lastName}`; }, },}); * * * Changes can take the form of function that passes previous state and returns new state or a value. Objects are always shallowly merged. Set values to undefined to delete them from the Store. In TypeScript, you can delete a value by using a non-null assertion, like `undefined!`. const [state, setState] = createStore({ firstName: "John", lastName: "Miller",});setState({ firstName: "Johnny", middleName: "Lee" });// ({ firstName: 'Johnny', middleName: 'Lee', lastName: 'Miller' })setState((state) => ({ preferredName: state.firstName, lastName: "Milner" }));// ({ firstName: 'Johnny', preferredName: 'Johnny', middleName: 'Lee', lastName: 'Milner' }) * * * To learn more about using stores check the Stores Guide, and the **Store utilities** section for more advanced APIs. --- ## Page: https://docs.solidjs.com/reference/store-utilities/modify-mutable `modifyMutable` streamlines the process of making multiple changes to a mutable Store, as obtained through the use of `createMutable`. It operates within a single `batch`, ensuring that dependent computations are updated just once, rather than triggering updates for each individual change. import { modifyMutable } from "solid-js/store"function modifyMutable<T>(mutable: T, modifier: (state: T) => T): void The function takes two arguments: 1. The first argument is the mutable Store that needs modification. 2. The second argument is a Store modifier, which could be one of those returned by `reconcile`. For example, if the UI depends on multiple fields of a mutable: import { createMutable } from "solid-js/store"const state = createMutable({ user: { firstName: "John", lastName: "Smith", },});<h1>Hello {state.user.firstName + " " + state.user.lastName}</h1>; Modifying n fields in sequence will cause the UI to update n times: state.user.firstName = "Jane";state.user.lastName = "Doe"; To trigger just a single update, the fields can be modified using a `batch`: import { batch } from "solid-js"batch(() => { state.user.firstName = "Jane"; state.user.lastName = "Doe";}); `modifyMutable` combined with `reconcile` or `produce` provides two alternate ways to do similar things: import { modifyMutable, reconcile } from "solid-js/store"// Replace state.user with the specified object (deleting any other fields)modifyMutable( state.user, reconcile({ firstName: "Jane", lastName: "Doe", })); import { modifyMutable, produce } from "solid-js/store"// Modify two fields in a batch, triggering just one updatemodifyMutable( state, produce((state) => { state.user.firstName = "Jane"; state.user.lastName = "Doe"; })); --- ## Page: https://docs.solidjs.com/reference/store-utilities/produce `produce` is an Immer inspired API for Solid's Store objects that allows the store to be mutated inside the `produce` function. import { produce } from "solid-js/store"import type { NotWrappable, Store } from "solid-js/store"function produce<T>( fn: (state: T) => void): ( state: T extends NotWrappable ? T : Store<T>) => T extends NotWrappable ? T : Store<T>; import { produce } from "solid-js/store";const [state, setState] = createStore({ user: { name: "John", age: 30, }, list: ["book", "pen"],});setState( produce((state) => { state.user.name = "Jane"; state.list.push("pencil"); })); --- ## Page: https://docs.solidjs.com/reference/store-utilities/reconcile Store utilitiesEdit this page `reconcile` is designed for diffing data changes in situations where granular updates cannot be applied. This is useful when dealing with immutable data from stores or handling large API responses. import { reconcile } from "solid-js/store"import type { NotWrappable, Store } from "solid-js/store"function reconcile<T>( value: T | Store<T>, options?: { key?: string | null; merge?: boolean; } = { key: "id" }): ( state: T extends NotWrappable ? T : Store<T>) => T extends NotWrappable ? T : Store<T> `reconcile` has a `key` option that can be used when available to match items. The `value` accepts either a value of type `T` or a Store containing values of type `T`. This represents the data to be reconciled. The `reconcile` function helps manage data changes by performing a diffing process, making it particularly handy in scenarios where applying granular updates is challenging or inefficient. The `key` and `merge` options provide flexibility to customize the reconciliation process based on specific needs. // subscribing to an observableconst unsubscribe = store.subscribe(({ todos }) => ( setState('todos', reconcile(todos)););onCleanup(() => unsubscribe()); ##### Options | Option | Type | Default | Description | | --- | --- | --- | --- | | key | string | "id" | Specifies the key to be used for matching items during reconciliation | | merge | boolean | false | When merge is false, referential checks are performed where possible to determine equality, and items that are not referentially equal are replaced. When merge is true, all diffing is pushed to the leaves, effectively morphing the previous data to the new value. | Report an issue with this page --- ## Page: https://docs.solidjs.com/reference/store-utilities/unwrap Store utilitiesEdit this page `unwrap` returns the underlying data in the store without a proxy. import { unwrap } from "solid-js/store"import type { Store } from "solid-js/store"function unwrap(store: Store<T>): T Report an issue with this page Previous ← reconcile Next getRequestEvent → --- ## Page: https://docs.solidjs.com/reference/server-utilities/get-request-event Solid uses Async Local Storage as a way of injecting the request context anywhere on the server. The server provides a utility function to access this context (called a `RequestEvent`). import { getRequestEvent } from "solid-js/web"import type { RequestEvent } from "solid-js/web"function getRequestEvent(): RequestEvent | undefined You can retrieve the request event by calling `getRequestEvent`: import { getRequestEvent } from "solid-js/web"const event = getRequestEvent() * * * `.request` is the most important property of the `RequestEvent`. This is a Web Request object that represents the current request to the server. You can access properties off of it such as `url` and `headers`. `body`, however, does not typically need to be handled directly for things such as server functions or rendering, which already handle mapping. import { getRequestEvent } from "solid-js/web"const event = getRequestEvent();if (event) { const auth = event.request.headers.get("Authorization");} * * * The `getRequestEvent` can also be used to stub out the Response - this extends the options that can be passed to the `Response constructor`. This is kept up to date so it can be used to read and write headers and status for the current response. import { getRequestEvent } from "solid-js/web"const event = getRequestEvent();if (event) { event.response.headers.append("Set-Cookie", "foo=hello"); event.response.status = 201;} ### Change event.response or create a new Response The `getRequestEvent` event is considered global and lasts the life of the request. Therefore, if you are calling a server function on the server during SSR or an RPC call, setting values on `event.response` will reflect on that request. The returned response will only impact the response when it is an RPC call. This is important because some headers previously set may not be needed to be set for the whole page, but only for a specific request. **Note:** This is important to keep in mind when choosing where to set headers and responses.