Skip to content

upgrade: props package upgrade for Solid 2.0#908

Draft
davedbase wants to merge 3 commits into
solidjs-community:nextfrom
davedbase:update/v2/props
Draft

upgrade: props package upgrade for Solid 2.0#908
davedbase wants to merge 3 commits into
solidjs-community:nextfrom
davedbase:update/v2/props

Conversation

@davedbase
Copy link
Copy Markdown
Member

Summary

Upgrades the props package to solid-js@^2.0.0-beta.13 / @solidjs/web@^2.0.0-beta.13 and adds two new utilities: combineHandlers and partitionProps.


Breaking changes

Peer dependencies updated
solid-js@^2.0.0-beta.13 and @solidjs/web@^2.0.0-beta.13 are now required.

classList support removed
Solid 2.0 removes the classList JSX prop in favour of class accepting objects and arrays. combineProps no longer handles a classList key. Pass an object or array as class instead:

// Before
combineProps(props, { classList: { active: isActive() } })
// After
combineProps(props, { class: { active: isActive() } })

class combining semantics updated
When all combined class values are strings they are joined with a space (unchanged). When any value is a ClassList object or array the result is a flat array, which Solid 2.0's class prop accepts natively.

merge replaces mergeProps semantics
Non-special props now follow merge semantics: an explicit undefined in a later source overrides earlier values (previously undefined was skipped).


New utilities

combineHandlers
Chains multiple event handlers into one. Handlers that are null, undefined, or false are silently skipped — useful for conditional handlers inline. Returns the single handler unchanged when only one is present (no wrapping overhead). Reactive through Solid's props proxy when used in JSX; for a standalone signal source, read it explicitly before passing or wrap the call in createMemo.

<button onClick={combineHandlers(props.onClick, internalHandler)} />
<div onKeyDown={combineHandlers(props.onKeyDown, isOpen() ? closeOnEsc : null)} />

partitionProps
Splits a props object into [matched, rest] — both views are lazy reactive proxies powered by filterProps under the hood, so the predicate runs per property read and both halves stay in sync with dynamic props. For an expensive predicate, pass a createPropsPredicate result to share a single cache across both views.

const [ownProps, htmlProps] = partitionProps(props,
  key => ["label", "variant", "size"].includes(key as string)
);
return <button {...htmlProps}>{ownProps.label}</button>;

Internal changes

  • mergePropsmerge, MergePropsMerge throughout
  • JSX type imported from @solidjs/web
  • createMemo(fn, undefined, options)createMemo(fn, options) (initialValue arg removed in 2.0)
  • Tests: createComputed replaced with createEffect(compute, apply) + flush(); signals created outside createRoot to avoid SIGNAL_WRITE_IN_OWNED_SCOPE
  • SSR test file added (test/server.test.ts)

@davedbase davedbase added this to the Solid 2.0 Migration milestone May 21, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: bf6ec8e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solid-primitives/props Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant