A declarative JavaScript library for building user interfaces with fine-grained reactivity.
—
Function-based component system with props utilities, lifecycle hooks, and component creation functions for building modular UI components.
Create and manage component instances with optimized rendering and lifecycle management.
/**
* Creates a component instance
* @param Comp - Component function to instantiate
* @param props - Props to pass to the component
* @returns JSX element
*/
function createComponent<T extends Component<any>>(
Comp: T,
props: ComponentProps<T>
): JSX.Element;
/**
* Lazy load a function component asynchronously
* @param fn - Function that returns a promise with the component
* @returns Lazy component with preload capability
*/
function lazy<T extends Component<any>>(
fn: () => Promise<{ default: T }>
): T & { preload: () => Promise<{ default: T }> };
/**
* Creates a unique identifier for components
* @returns Unique string identifier
*/
function createUniqueId(): string;Usage Examples:
import { createComponent, lazy } from "solid-js";
// Creating component instances
function App() {
return createComponent(UserProfile, {
name: "John",
age: 30
});
}
// Lazy loading components
const LazyUserDashboard = lazy(() => import("./UserDashboard"));
function App() {
return (
<div>
<LazyUserDashboard userId="123" />
</div>
);
}
// Preloading lazy components
LazyUserDashboard.preload();
// Using unique IDs
function FormField() {
const id = createUniqueId();
return (
<div>
<label for={id}>Name:</label>
<input id={id} type="text" />
</div>
);
}Merge and split props objects with reactive updates and type safety.
/**
* Merges multiple props objects reactively
* @param sources - Props objects to merge
* @returns Merged props object
*/
function mergeProps<T extends Record<string, any>[]>(
...sources: T
): MergeProps<T>;
/**
* Splits props into multiple objects based on keys
* @param props - Props object to split
* @param keys - Arrays of keys to extract into separate objects
* @returns Array of split props objects
*/
function splitProps<T extends Record<string, any>, K extends (keyof T)[][]>(
props: T,
...keys: K
): SplitProps<T, K>;
type MergeProps<T extends Record<string, any>[]> = T extends [
infer First,
...infer Rest
]
? First & MergeProps<Rest>
: {};
type SplitProps<T, K> = K extends [infer First, ...infer Rest]
? First extends (keyof T)[]
? [Pick<T, First[number]>, ...SplitProps<Omit<T, First[number]>, Rest>]
: []
: [T];Usage Examples:
import { mergeProps, splitProps, createSignal } from "solid-js";
// Merging props
function Button(props) {
const merged = mergeProps(
{ type: "button", disabled: false },
props
);
return <button {...merged} />;
}
// Splitting props
function Input(props) {
const [inputProps, otherProps] = splitProps(props, ["value", "onInput", "placeholder"]);
return (
<div {...otherProps}>
<input {...inputProps} />
</div>
);
}
// Complex props handling
function CustomComponent(props) {
const [local, buttonProps, divProps] = splitProps(
props,
["label", "required"],
["onClick", "disabled"],
["class", "style"]
);
const defaultProps = { disabled: false, required: false };
const mergedLocal = mergeProps(defaultProps, local);
return (
<div {...divProps}>
{mergedLocal.required && <span>*</span>}
<label>{mergedLocal.label}</label>
<button {...buttonProps} disabled={mergedLocal.disabled || buttonProps.disabled}>
Click me
</button>
</div>
);
}Resolve and interact with component children in reactive contexts.
/**
* Resolves child elements to help interact with children
* @param fn - Accessor function that returns JSX children
* @returns Resolved children with helper methods
*/
function children(fn: Accessor<JSX.Element>): ChildrenReturn;
interface ChildrenReturn {
(): ResolvedJSXElement;
toArray(): ResolvedJSXElement[];
}
type ResolvedJSXElement = Element | Text | string | number;Usage Examples:
import { children, For } from "solid-js";
// Resolving children
function Container(props) {
const c = children(() => props.children);
return (
<div class="container">
<div class="header">Container has {c.toArray().length} children</div>
{c()}
</div>
);
}
// Working with children in custom components
function List(props) {
const c = children(() => props.children);
return (
<ul>
<For each={c.toArray()}>
{(child, index) => (
<li data-index={index()}>
{child}
</li>
)}
</For>
</ul>
);
}
// Usage
function App() {
return (
<Container>
<span>First child</span>
<span>Second child</span>
<span>Third child</span>
</Container>
);
}/**
* A general Component has no implicit children prop
*/
type Component<P = {}> = (props: P) => JSX.Element;
/**
* Component that forbids children prop
*/
type VoidComponent<P = {}> = Component<VoidProps<P>>;
/**
* Component that allows optional children prop
*/
type ParentComponent<P = {}> = Component<ParentProps<P>>;
/**
* Component that requires children prop with specific type
*/
type FlowComponent<P, C> = Component<FlowProps<P, C>>;type VoidProps<P> = P & { children?: never };
type ParentProps<P> = P & { children?: JSX.Element };
type FlowProps<P, C> = P & { children: C };
type ComponentProps<T extends keyof JSX.IntrinsicElements | Component<any>> =
T extends Component<infer P>
? P
: T extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[T]
: {};declare namespace JSX {
type Element = any;
interface IntrinsicElements {
[elemName: string]: any;
}
interface ElementChildrenAttribute {
children: {};
}
}import { Component, createMemo } from "solid-js";
// HOC for adding loading state
function withLoading<P extends object>(
WrappedComponent: Component<P>
): Component<P & { loading?: boolean }> {
return (props) => {
const loading = createMemo(() => props.loading ?? false);
if (loading()) {
return <div>Loading...</div>;
}
return <WrappedComponent {...props} />;
};
}
// Usage
const UserProfileWithLoading = withLoading(UserProfile);import { Component, JSX } from "solid-js";
interface RenderPropsComponent<T> {
children: (data: T) => JSX.Element;
data: T;
}
function DataProvider<T>(props: RenderPropsComponent<T>): JSX.Element {
return <div>{props.children(props.data)}</div>;
}
// Usage
function App() {
return (
<DataProvider data={{ name: "John", age: 30 }}>
{(user) => (
<div>
<h1>{user.name}</h1>
<p>Age: {user.age}</p>
</div>
)}
</DataProvider>
);
}import { ParentComponent, JSX } from "solid-js";
// Compound component pattern
const Card: ParentComponent & {
Header: ParentComponent;
Body: ParentComponent;
Footer: ParentComponent;
} = (props) => {
return <div class="card">{props.children}</div>;
};
Card.Header = (props) => <div class="card-header">{props.children}</div>;
Card.Body = (props) => <div class="card-body">{props.children}</div>;
Card.Footer = (props) => <div class="card-footer">{props.children}</div>;
// Usage
function App() {
return (
<Card>
<Card.Header>
<h2>Card Title</h2>
</Card.Header>
<Card.Body>
<p>Card content goes here.</p>
</Card.Body>
<Card.Footer>
<button>Action</button>
</Card.Footer>
</Card>
);
}Install with Tessl CLI
npx tessl i tessl/npm-solid-js