Replies: 3 comments
|
Yes, what you are seeing is expected — but On a DOM element, import { splitProps, type JSX, type Component } from 'solid-js';
type ButtonProps = JSX.ButtonHTMLAttributes<HTMLButtonElement>;
const Button: Component<ButtonProps> = (rawProps) => {
const [local, rest] = splitProps(rawProps, ['class', 'classList']);
return (
<button
{...rest}
class={local.class}
classList={{
'bg-color': true,
...local.classList
}}
/>
);
};That makes the behavior predictable. Why your |
|
Both behaviors are expected and intentional — they come from two different merging mechanisms. Case 1: <button classList={{ 'bg-color': true }} {...props}></button>SolidJS compiles JSX spreads through You can read more in the SolidJS docs on mergeProps — the key line is: "mergeProps merges potentially reactive objects without losing reactivity, giving special treatment to class, classList, style, and ref." Case 2: spreading a plain object literal → override (not merge) const borderColor = { classList: { 'border-color': true } };
<Button classList={{ 'text-color': true }} {...borderColor}>Here you're spreading a plain non-reactive JS object, not a SolidJS props object. The JSX compiler treats this as a standard JS object spread — Is it reliable? Yes for case 1. The merge behavior on Can you use merge without the parent→child pattern? Yes — call const merged = mergeProps(
{ classList: { 'text-color': true } },
borderColor
);
<Button {...merged}>This gives you the same merge semantics anywhere, not just in component bodies. |
|
Yes, this is expected and reliable. Solid's JSX compiler has special handling for This is documented in the Solid docs under "Spreading" — spread props get merged with existing props, and for certain "mergeable" attributes ( So in your Button example: <button classList={{ 'bg-color': true }} {...props}>The compiler generates code that merges the component's own The reason your second example doesn't work: const borderColor = { classList: { 'border-color': true } };
<Button classList={{ 'text-color': true }} {...borderColor}>This is applying the spread at the parent level (on If you flip the order it'd work: <Button {...borderColor} classList={{ 'text-color': true }}>But even then, the merging only happens inside the component where |
|
This behavior is expected and is due to the difference between how SolidJS handles props on custom components vs. native HTML/DOM elements:
If you need to merge dynamic classes from a parent into a child component, the standard best practice is to pass them via the const Button: Component<JSX.ButtonHTMLAttributes<HTMLButtonElement>> = (props) => {
return (
<button
class={`bg-color ${props.class ?? ''}`}
{...props}
></button>
);
}; |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I got a confusing case where
classListdoes not override but merge classes when passed from parent to child.That
Buttongets both classes applied.Is it something expected and where I can read more on how and why?
I find it useful, but is it reliable?
Is it possible to use it without the parent->child passed props?
For example the following does not work
Example playground: https://stackblitz.com/edit/github-te6jt77k?file=src%2FApp.tsx
All reactions