Skip to content

fix(core): keep null-valued props spread into a component - #9193

Merged
Varixo merged 1 commit into
QwikDev:mainfrom
intellix:fix/jsx-split-keep-null-component-props
Oct 9, 2026
Merged

Varixo merged 1 commit into
QwikDev:mainfrom
intellix:fix/jsx-split-keep-null-component-props

Conversation

@intellix

@intellix intellix commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

What is it?

  • Bug

Description

Spreading an object into a component drops every key whose value is null:

const Child = component$((props: { a: number; s: { p: number } | null }) => (
  <span>{JSON.stringify(Object.keys(props))}</span>
));

const data = { a: 1, s: null };
<Child {...data} />          // ["a"]: `s` is gone
<Child a={1} s={null} />      // ["a", "s"]

The key is missing only when it's spread. Explicit props keep null, and an undefined value survives the spread. A component typed s: T | null therefore gets undefined, and props.s !== null is true. We hit this in a list built by spreading GraphQL results into a card component. GraphQL uses null for absent values, so every card read as "sponsored". On v1 the null arrives.

Cause

When there's a spread, the optimizer emits _jsxSplit. At the end it removes every null var prop:

} else if (varProps[k] === null) {
  ...
  // Clean up null markers (from event conversions)
  delete varProps[k];
}

Those markers come from event-prop conversion, which _jsxSplit only does for native elements (typeof type === 'string'). On a component the same check deletes real props.

Fix

Only run the null cleanup for native elements, the same condition _jsxSplit already uses for its other element-only transforms. Elements are unchanged: a spread null attribute is still dropped, which is what null means for an attribute.

Tests

A new test in component.spec.tsx spreads { a: 1, s: null } into a component and checks s arrives as null. It runs under both ssrRenderToDom and domRender, fails on main (expected 'false:false' to be 'true:true'), and passes with the fix. The full packages/qwik/src/core suite passes (2394 tests).

Checklist

  • My code follows the developer guidelines of this project
  • I performed a self-review of my own code
  • I added a changeset with pnpm change
  • I added new tests to cover the fix / functionality

_jsxSplit deletes every null var prop to clean up event-conversion markers,
but that conversion only happens on native elements. On a component it
dropped real props, so `{...{ s: null }}` arrived without `s` while
`s={null}` kept it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@intellix
intellix requested a review from a team as a code owner October 9, 2026 15:53
@changeset-bot

changeset-bot Bot commented Oct 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b1b6348

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

This PR includes changesets to release 8 packages
Name Type
@qwik.dev/core Patch
@qwik.dev/devtools Patch
eslint-plugin-qwik Patch
@qwik.dev/mcp Patch
@qwik.dev/react Patch
@qwik.dev/router Patch
@qwik.dev/utils Patch
create-qwik Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Oct 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@qwik.dev/core

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/core@9193

@qwik.dev/router

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/router@9193

@qwik.dev/utils

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/utils@9193

eslint-plugin-qwik

npm i https://pkg.pr.new/QwikDev/qwik/eslint-plugin-qwik@9193

create-qwik

npm i https://pkg.pr.new/QwikDev/qwik/create-qwik@9193

@qwik.dev/optimizer

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/optimizer@9193

@qwik.dev/devtools

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/devtools@9193

@qwik.dev/mcp

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/mcp@9193

commit: b1b6348

@Varixo Varixo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@Varixo
Varixo merged commit 5d6d34a into QwikDev:main Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants