Skip to content

fix: prevent orphan elements from rendering#94

Merged
megheaiulian merged 1 commit intomainfrom
fix/start-inactive
Feb 1, 2026
Merged

fix: prevent orphan elements from rendering#94
megheaiulian merged 1 commit intomainfrom
fix/start-inactive

Conversation

@cristinecula
Copy link
Contributor

Summary

Elements that are constructed but never connected to the DOM (orphan elements) will no longer render or run effects. This fixes issues where lit-html creates elements during template parsing that are never inserted into the DOM.

Problem

When lit-html renders a template containing a Pion custom element, it may create orphan elements - elements that are constructed but never connected to the DOM. Previously, these orphan elements would still render and run effects because Pion's scheduler started with _active = true.

This caused issues like:

  • Multiple instances of hooks being created for what should be a single component
  • Global event handlers being registered from orphan elements
  • Keyboard navigation breaking due to duplicate handlers

Solution

The scheduler now starts with _active = false and only activates when:

  • connectedCallback is called (for custom elements)
  • resume() is called explicitly (for virtual components)

Changes

  • src/scheduler.ts: Changed _active initialization from true to false
  • src/virtual.ts: Added resume() call before update() since virtual components don't have connectedCallback
  • test/use-effects.test.ts: Added test case for orphan elements not rendering

Testing

  • All 67 existing tests pass
  • New test "Does not render or run effects for elements that are never connected" verifies the fix
  • Manually verified in cosmoz-dropdown that keyboard navigation now works correctly

Fixes #64

Elements that are constructed but never connected to the DOM will no longer
render or run effects. This fixes issues where lit-html creates elements
during template parsing that are never inserted into the DOM.

The scheduler now starts with _active = false and only activates when
connectedCallback is called (for custom elements) or resume() is called
explicitly (for virtual components).

Fixes #64
@changeset-bot
Copy link

changeset-bot bot commented Feb 1, 2026

🦋 Changeset detected

Latest commit: 4cddfc7

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

This PR includes changesets to release 1 package
Name Type
@pionjs/pion Minor

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

@netlify
Copy link

netlify bot commented Feb 1, 2026

Deploy Preview for pionjs ready!

Name Link
🔨 Latest commit 4cddfc7
🔍 Latest deploy log https://app.netlify.com/projects/pionjs/deploys/697f86280ec46c00083ce28d
😎 Deploy Preview https://deploy-preview-94--pionjs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@cristinecula cristinecula marked this pull request as ready for review February 1, 2026 17:01
@cristinecula cristinecula requested a review from a team February 1, 2026 17:01
@cristinecula cristinecula self-assigned this Feb 1, 2026
@megheaiulian megheaiulian merged commit 9b813bf into main Feb 1, 2026
9 checks passed
@megheaiulian megheaiulian deleted the fix/start-inactive branch February 1, 2026 17:25
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.

Effects can run after the element is torn-down

2 participants