What Are Props in SolidJS?
Props are read-only properties passed from a parent component to a child component. These reactive proxies are accessible within the component via the props object and enable fine-grained reactivity throughout your component tree. Unlike React, where components re-render when props change, SolidJS updates only the specific DOM nodes that depend on changed prop values, resulting in superior runtime performance.
Our web development services team leverages modern frameworks like SolidJS to build applications that deliver exceptional performance and user experience.
Key Characteristics of SolidJS Props
- Read-only: Props cannot be modified by the receiving component
- Reactive: Changes to props automatically update dependent DOM nodes
- Proxy-based: SolidJS uses proxies to track dependencies and update efficiently
- Component-scoped: Each component receives its own props object
Props are the fundamental mechanism for component communication in SolidJS, but they work fundamentally differently from other frameworks. According to the SolidJS documentation on props, this approach enables fine-grained reactivity where components run once and updates happen directly at the DOM level based on dependency tracking.
Understanding the fundamental differences from other frameworks
Fine-Grained Reactivity
Only affected DOM nodes update when props change, not entire component trees
Components Run Once
SolidJS components execute only once, not on every render cycle
Automatic Dependency Tracking
No need for useMemo or useCallback to maintain referential integrity
Proxy-Based Updates
Props are reactive proxies that automatically track and update dependencies
Basic Prop Usage
Passing Props from Parent Components
Parent components pass props to children as JSX attributes. Any valid JavaScript value can be passed, including strings, numbers, objects, arrays, and functions.
Accessing Props in Child Components
Child components receive props via the props object. Direct destructuring in SolidJS breaks reactivity because it extracts values at component initialization. Instead, access props directly through the props object or use splitProps to maintain reactivity.
// WRONG - Direct destructuring loses reactivity
const { name } = props; // Creates a static value
// CORRECT - Access props directly
return <h1>{props.name}</h1>
// CORRECT - Use splitProps for organized access
const [localProps] = splitProps(props, ['name', 'age']);
return <h1>{localProps.name}</h1>
When building modern web applications with reactive frameworks, understanding these patterns is essential for creating maintainable component architectures. As explained in LogRocket's comprehensive guide to SolidJS props, direct destructuring extracts values at component initialization, creating static values that won't update when parent props change.
1interface ButtonProps {2 /** The button label text */3 label: string;4 /** Callback fired when button is clicked */5 onClick: () => void;6 /** Optional: button variant */7 variant?: 'primary' | 'secondary' | 'danger';8 /** Optional: disable button */9 disabled?: boolean;10}11 12function Button({ 13 label, 14 onClick, 15 variant = 'primary', 16 disabled = false 17}: ButtonProps) {18 return (19 <button 20 className={`btn btn-${variant}`}21 onClick={onClick}22 disabled={disabled}23 >24 {label}25 </button>26 );27}Default Values
Using mergeProps for Reactive Defaults
The mergeProps utility creates a new reactive object that merges multiple prop sources together. This is essential when defaults need to be reactive or when defaults depend on other prop values. As shown in the SolidJS tutorial on props and defaults, mergeProps preserves reactivity while providing default values.
import { mergeProps } from 'solid-js';
function UserCard(props) {
const merged = mergeProps(
props,
{
role: 'user',
avatar: '/default-avatar.png',
bio: 'No biography provided'
}
);
return (
<div>
<img src={merged.avatar} alt="Avatar" />
<h2>{props.name}</h2>
<p>Role: {merged.role}</p>
<p>Bio: {merged.bio}</p>
</div>
);
}
When building complex applications with SolidJS, mergeProps is particularly useful for combining base component styles with custom overrides, extending event handlers while preserving original behavior, and setting conditional defaults based on other prop values. Our experienced developers apply these patterns when building scalable web applications for clients across various industries.
The splitProps Function
The splitProps utility solves the fundamental problem of destructuring in SolidJS. It allows you to organize props into logical groups while preserving reactivity for each group.
Why splitProps Is Essential
Direct destructuring extracts values at component initialization, creating static values that won't update when parent props change. splitProps maintains reactivity by keeping each prop group as a reactive proxy.
import { splitProps } from 'solid-js';
function DataTable(props) {
const [tableProps, setProps] = splitProps(props, [
'columns',
'data',
'sortColumn',
'sortDirection'
]);
const [styleProps, rest] = splitProps(setProps, [
'class',
'style'
]);
return (
<table class={styleProps.class} style={styleProps.style}>
<thead>
<For each={tableProps.columns}>
{(col) => <th>{col.title}</th>}
</For>
</thead>
<tbody>
<For each={tableProps.data}>
{(row) => <tr {...rest}>{/* row cells */}</tr>}
</For>
</tbody>
</table>
);
}
This pattern is especially valuable when building reusable component libraries where you need clean APIs and want to prevent unknown props from being passed through to underlying elements.
| Scenario | Use splitProps | Use mergeProps |
|---|---|---|
| Organizing received props | ✓ | |
| Setting default values | ✓ | |
| Breaking props into groups | ✓ | |
| Combining prop sources | ✓ | |
| Passing unknown props through | ✓ | |
| Making destructured props reactive | ✓ |
Passing Props to Children
The children prop is special in SolidJS. It represents the content passed between component tags and can be accessed and manipulated like other props.
import { children, mergeProps } from 'solid-js';
function Card(props) {
const resolvedChildren = children(() => props.children);
return (
<div class="card">
<header><h2>{props.title}</h2></header>
<main>{resolvedChildren()}</main>
<footer>{props.footer}</footer>
</div>
);
}
// Usage
<Card title="Welcome">
<p>This is card content.</p>
</Card>
The children prop enables powerful composition patterns. Combined with splitProps and mergeProps, you can build flexible component APIs that feel natural and intuitive.
Prop Drilling and Alternatives
When data must pass through multiple component layers that don't use it, prop drilling becomes problematic. SolidJS provides the Context API as an alternative.
When to Use Context Instead
Use context when data needs to reach deeply nested components (3+ levels), multiple components at different levels need the same data, or the data is truly global like user authentication or theme settings.
import { createContext, useContext, createSignal } from 'solid-js';
const UserContext = createContext();
function UserProvider(props) {
const [user, setUser] = createSignal(null);
const value = {
user,
login: (userData) => setUser(() => userData),
logout: () => setUser(null)
};
return (
<UserContext.Provider value={value}>
{props.children}
</UserContext.Provider>
);
}
function UserAvatar() {
const { user, logout } = useContext(UserContext);
return user() ? (
<div class="avatar">
<img src={user().avatar} />
<button onClick={logout}>Logout</button>
</div>
) : <button>Login</button>;
}
Choosing between props and context is an important architectural decision. Props work best when data flows through only 1-2 component levels, while context shines when dealing with truly global data like user sessions or theme settings. Our web development services team helps clients architect scalable solutions that balance simplicity and maintainability.
Frequently Asked Questions
Why don't SolidJS components re-render?
SolidJS uses fine-grained reactivity. Components run only once, and updates happen directly at the DOM level based on dependency tracking, making re-renders unnecessary.
When should I use splitProps vs destructuring?
Always use splitProps when you need to maintain reactivity. Use destructuring only for non-reactive local variables that don't depend on prop changes.
Can I use both mergeProps and splitProps?
Yes! They're often used together: use mergeProps to set defaults, then splitProps to organize the resulting props into logical groups.
How do I type optional props in TypeScript?
Use TypeScript's optional marker (?) for props that aren't required. Provide sensible defaults in your component logic for optional values.
Sources
- LogRocket: Understanding SolidJS props: A complete guide - Comprehensive tutorial covering basic to advanced prop patterns with practical examples
- SolidJS Documentation: Props - Official documentation covering props, mergeProps, and splitProps
- SolidJS Tutorial: Props and Default Props - Interactive tutorials on props defaults and mergePatterns