Skip to content

fix(core): keep the next sibling's effects when inserting a component - #9230

Open
ybai08 wants to merge 1 commit into
QwikDev:mainfrom
ybai08:fix/9189-keep-sibling-effects-on-component-insert
Open

ybai08 wants to merge 1 commit into
QwikDev:mainfrom
ybai08:fix/9189-keep-sibling-effects-on-component-insert

Conversation

@ybai08

@ybai08 ybai08 commented Oct 18, 2026

Copy link
Copy Markdown

What is it?

  • Bug

Description

Fixes #9189.

Once a conditional component has been rendered in front of an element, that element's signal-bound attributes stop updating:

{!!error.value && <Alert message={error.value} />}
<button aria-busy={busy.value || undefined} class={['pay', busy.value && 'busy']} ... />

After "Card declined" shows the <Alert>, later changes to busy no longer reach the button's class / aria-busy.

The attributes are lost when the <Alert> is inserted, not when it is removed. The issue sees it on the next click, because that is the first busy change afterwards.

Cause: in expectComponent, when moveOrCreateKeyedNode finds no host for the component, insertNewComponent(diffContext, host, ...) is called with host = vNewNode || vCurrent. In that branch host is just the vnode at the cursor, here the <button>. It is not a component being replaced. insertNewComponent runs clearAllEffects on it, which removes the button's subscriptions to busy. The two other insertNewComponent calls do replace host (same key but a different component, or props changed without a key), and clearing there is intended.

Fix: pass null from the moveOrCreateKeyedNode branch. The vnode left at the cursor is either matched by a later JSX node, so it must keep its effects, or removed by expectNoMore / cleanupSideBuffer, which already run cleanup and clear its effects.

Test: render-regression.spec.tsx > issue #9189 follows the issue's steps for both ssrRenderToDom and domRender: pay, decline (Alert appears), pay again. The last step expects class="pay busy" and aria-busy="true".

Commands run (Node 22, pnpm build.core.dev first):

  • pnpm vitest run packages/qwik/src/core/tests/render-regression.spec.tsx -t "9189": 2 failed (expected 'pay' to be 'pay busy') with the fix reverted; 2 passed with it.
  • pnpm vitest run packages/: 3854 passed, 7 failed. The 7 failures are all in qwik-vite/src/plugins/plugin.unit.ts and also fail on main in this environment (Cannot find module .../bindings/qwik.wasm.mjs, no Rust/WASM build). On main the same run gives 3852 passed, 7 failed. Packages whose dependencies were not installed (devtools, docs, mcp, browser-extension) fail to import in both runs.
  • pnpm test.e2e.chromium (dev build): 580 passed, 1 failed, 2 skipped, 1 did not run. The failure is ssg-snapshot.e2e.ts › "core chunk brotli size stays within budget". It also fails on main with the dev build (36783 bytes on main, 36755 on this branch, budget 34800). The test itself says it expects the production build, which was not built here.
  • prettier --check and eslint on the changed files: clean.

Not run: pnpm build.core / api.update (no public API change), the Rust optimizer, the e2e suites with QWIK_OPTIMIZER=rust, the production build for the brotli budget check.

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

When a new component is inserted because no matching host was found,
the vnode at the cursor is an unrelated sibling, not a host being
replaced. Clearing its effects dropped the sibling's signal bindings,
so its attributes stopped updating.

Fixes QwikDev#9189
@ybai08
ybai08 requested a review from a team as a code owner October 18, 2026 11:37
@changeset-bot

changeset-bot Bot commented Oct 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: def81f4

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

This branch has not been deployed

No deployments
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.

[🐞] Attribute updates are dropped when a conditional component is removed in the same render

1 participant