Props and Reactivity Gotchas
The single most common Solid mistake for React developers — destructuring props breaks reactivity — and how to avoid it.
2 min read
Props in Solid are reactive, but only if you access them in a way that preserves their connection to the parent's signals. This lesson covers the mistake nearly every developer coming from React makes at least once — usually without any error message to point them at it.
The mistake: destructuring props
// Parent
function App() {
const [name, setName] = createSignal("Ana");
return <Greeting name={name()} />;
}
// Child — looks completely reasonable, and is broken
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}This looks idiomatic — it's exactly how you'd write a React component. But remember: Greeting's function body runs once. Destructuring { name } in the parameter list reads props.name a single time, at that moment, and assigns the plain string to a local variable. When setName(...) is called later, nothing updates — name inside Greeting was never a live reference to the prop, just a one-time copy.
The fix: access props through the props object
function Greeting(props) {
return <h1>Hello, {props.name}!</h1>;
}This works because props.name is a property access inside JSX, evaluated fresh every time Solid needs to update that binding — not a value captured once during setup. Solid's props object is itself built with getters, so reading props.name at the point of use (inside JSX, a memo, or an effect) stays connected to the source signal. Reading it once and storing the result — via destructuring or assignment to a local variable — breaks that connection, the same way unwrapping a signal into a plain variable does.
What if you genuinely need to destructure?
Solid provides splitProps and mergeProps for the cases where you need to reshape props without losing reactivity:
import { splitProps } from "solid-js";
function Button(props) {
const [local, others] = splitProps(props, ["variant"]);
return (
<button class={`btn btn-${local.variant}`} {...others}>
{others.children}
</button>
);
}splitProps separates a props object into named groups while keeping every field reactive — local.variant still tracks changes, it's just organized differently than props.variant. This is the idiomatic way to pick specific props out of the object (say, to handle separately from the rest) without falling into the destructuring trap.
The same rule applies to function arguments in general
// Broken — reads count() once when the callback is defined
function logCount(value = count()) { console.log(value); }
// Fine — reads count() fresh each time it's called
function logCount() { console.log(count()); }The underlying principle, worth internalizing beyond just props: in Solid, reactivity survives only through function calls made at the point of use. The moment you store a signal's or prop's current value in a plain variable — via destructuring, default parameters, or a one-off assignment — you've frozen it. Keep the access as a function call (props.x, signal()) as close as possible to where it's actually used.