Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Props

Props are data that a parent component passes to a child through attributes. The component receives them as one props object. In Solid this object is reactive: its fields are read at the moment you access them, so how you read them matters.

Passing props

The component reads the task text from props.title:

// src/components/TodoItem.jsx
export default function TodoItem(props) {
  return <li>{props.title}</li>;
}

The parent passes the value as an attribute:

// src/App.jsx
import TodoItem from './components/TodoItem';
 
export default function App() {
  return (
    <ul>
      <TodoItem title="Buy milk" />
      <TodoItem title="Call Oleg" />
    </ul>
  );
}

The page shows two items with different text.

A prop from a signal

If you pass a signal to a prop, the child updates along with it:

// src/App.jsx
import { createSignal } from 'solid-js';
import TodoItem from './components/TodoItem';
 
export default function App() {
  const [title, setTitle] = createSignal('Buy milk');
 
  return (
    <div>
      <ul>
        <TodoItem title={title()} />
      </ul>
      <button onClick={() => setTitle('Buy bread')}>Change</button>
    </div>
  );
}

After the click the item's text changes. The Solid compiler turns title={title()} into a getter, so props.title reads the fresh value every time.

Why not to destructure

CodeResult
function TodoItem(props) and props.title in JSXUpdates
function TodoItem({ title })Read once and frozen
const title = props.title in the bodyAlso frozen

Destructuring reads the field immediately, when the component is called, and the component is called only once.

Defaults: mergeProps

// src/components/TodoItem.jsx
import { mergeProps } from 'solid-js';
 
export default function TodoItem(props) {
  const merged = mergeProps({ priority: 'normal' }, props);
 
  return <li>{merged.title} ({merged.priority})</li>;
}

mergeProps combines objects while keeping reactivity. Without a priority attribute the item shows "normal".

Splitting props: splitProps

// src/components/Button.jsx
import { splitProps } from 'solid-js';
 
export default function Button(props) {
  const [local, others] = splitProps(props, ['label']);
 
  return <button class="btn" {...others}>{local.label}</button>;
}

local gets label, and others gets everything else, such as onClick or disabled, which goes to the button as a whole. Usage: <Button label="Add" onClick={add} />.

Children

Content between the opening and closing tag arrives in props.children:

// src/components/Card.jsx
export default function Card(props) {
  return <section class="card">{props.children}</section>;
}

<Card><p>No tasks</p></Card> renders the paragraph inside section.

Common mistake

Writing a component out of React habit — function TodoItem({ title }). At first everything seems to work, but when the parent's data changes, the text does not update. Always accept props as a whole and read props.title right in JSX.

Thanks for reading!

Donate to the site — we work hard for you.