Skip to content

fix: increment vnode._original to make sure the component is re-ren…#2126

Open
HuJean wants to merge 1 commit intomainfrom
p/fix-globalProps
Open

fix: increment vnode._original to make sure the component is re-ren…#2126
HuJean wants to merge 1 commit intomainfrom
p/fix-globalProps

Conversation

@HuJean
Copy link
Copy Markdown
Collaborator

@HuJean HuJean commented Jan 22, 2026

#2125

Summary by CodeRabbit

  • Bug Fixes

    • Ensure components reliably re-render when global properties are updated in edge cases where previous updates could be skipped.
  • Tests

    • Expanded lifecycle tests to cover more update scenarios, hydration flows, and propagation of global prop changes.
  • Changelog

    • Added a patch release entry documenting the behavioral fix.

✏️ Tip: You can customize this high-level summary in your review settings.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@HuJean HuJean requested a review from hzy as a code owner January 22, 2026 05:38
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Jan 22, 2026

🦋 Changeset detected

Latest commit: 1653b8f

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

This PR includes changesets to release 1 package
Name Type
@lynx-js/react 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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

This change bumps vnode ORIGINAL in runWithForce to force re-renders when updateGlobalProps runs (including non-component root vnodes), adds tests covering updateGlobalProps lifecycles, and adds a changelog entry documenting the patch.

Changes

Cohort / File(s) Summary
Changelog
\.changeset/full-clubs-train.md
Add patch release entry describing the runWithForce ORIGINAL bump to force re-renders when updateGlobalProps is used.
Core Runtime Fix
packages/react/runtime/src/lynx/runWithForce.ts
Modify DIFF2 hook to increment vnode[ORIGINAL] when new and old ORIGINAL values are equal, ensuring FORCE path triggers updates.
Tests
packages/react/runtime/__test__/lifecycle/updateGlobalProps.test.jsx
Expand test scaffolding and add multiple scenarios validating updateGlobalProps across root/page/component render paths, hydration, and element-tree updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • hzy
  • Yradex
  • colinaaa

Poem

🐰 I nudge the ORIGINAL, give vnodes a shove,
I wake sleepy roots with a hop and a love.
When props shift and nothing will stir,
I bump a number — render occurs!
Hooray for small hops that fix big things.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: incrementing vnode._original to force component re-renders, which matches the core changes in runWithForce.ts and the changelog entry.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch p/fix-globalProps

Tip

🧪 Unit Test Generation v2 is now available!

We have significantly improved our unit test generation capabilities.

To enable: Add this to your .coderabbit.yaml configuration:

reviews:
  finishing_touches:
    unit_tests:
      enabled: true

Try it out by using the @coderabbitai generate unit tests command on your code files or under ✨ Finishing Touches on the walkthrough!

Have feedback? Share your thoughts on our Discord thread!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Jan 22, 2026

CodSpeed Performance Report

Merging this PR will degrade performance by 5.35%

Comparing p/fix-globalProps (1653b8f) with main (d1b0d9e)

Summary

⚡ 2 improved benchmarks
❌ 1 regressed benchmark
✅ 60 untouched benchmarks
⏩ 3 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
basic-performance-nest-level-100 7.5 ms 7.1 ms +6.19%
basic-performance-div-10000 456.7 ms 482.5 ms -5.35%
transform 1000 view elements 46.3 ms 41.9 ms +10.28%

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link
Copy Markdown

relativeci bot commented Jan 22, 2026

Web Explorer

#7432 Bundle Size — 383.56KiB (0%).

1653b8f(current) vs d1b0d9e main#7429(baseline)

Bundle metrics  no changes
                 Current
#7432
     Baseline
#7429
No change  Initial JS 154.71KiB 154.71KiB
No change  Initial CSS 35.05KiB 35.05KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 8 8
No change  Modules 237 237
No change  Duplicate Modules 16 16
No change  Duplicate Code 2.99% 2.99%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#7432
     Baseline
#7429
No change  JS 252.66KiB 252.66KiB
No change  Other 95.85KiB 95.85KiB
No change  CSS 35.05KiB 35.05KiB

Bundle analysis reportBranch p/fix-globalPropsProject dashboard


Generated by RelativeCIDocumentationReport issue


const c = oldVNode[COMPONENT];
if (c) {
if (vnode[ORIGINAL] != null && oldVNode[ORIGINAL] === vnode[ORIGINAL]) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if (vnode[ORIGINAL] != null && oldVNode[ORIGINAL] === vnode[ORIGINAL]) {
if (vnode !=== oldVNode && vnode[ORIGINAL] != null && oldVNode[ORIGINAL] === vnode[ORIGINAL]) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we can remove line 11-22 if we do this.

// In https://github.com/preactjs/preact/pull/4724, preact will
// skip render if the `vnode._original` is not changed, even if `c._force` is true
// So we need to increment `vnode._original` to make sure the `__root.__jsx` is re-rendered
// This is the same logic with: https://github.com/preactjs/preact/blob/43178581442fa0f2428e5bdbca355860b2d12e5d/src/component.js#L131
if (__root.__jsx) {
const newVNode = Object.assign({}, __root.__jsx) as unknown as VNode;
if (newVNode[ORIGINAL] != null) {
newVNode[ORIGINAL] += 1;
// @ts-expect-error: __root.__jsx is a VNode
__root.__jsx = newVNode;
}
}

@HuJean HuJean force-pushed the p/fix-globalProps branch from 62ef34d to 1653b8f Compare January 30, 2026 05:18
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. If this pull request is still relevant, please leave any comment (for example, "bump").

@github-actions github-actions bot added the stale Inactive for 30 days. Will be closed by bots. label Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework:React stale Inactive for 30 days. Will be closed by bots.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants